Define the cons (: :) command for custom collections

I use the fairly popular FSharpx.Collections package, and in particular NonEmptyList .

This type provides the NonEmptyList.cons function, but I want to use the :: operator as with a normal List , i.e. head :: tail . Since tail should already be NonEmptyList<'a> , there should be NonEmptyList<'a> conflict with the List :: operator.

However, it seems I can not determine the operator. It:

 let ( :: ) ht = NonEmptyList.cons ht 

leads to a compilation error:

 Unexpected symbol '::' in pattern. Expected ')' or other token. 

I know that :: not quite in the same category as other operators, but I do not quite understand how to do this. So I tried several things more or less at random, such as replacing :: with op_cons , etc. Without success.

Am I missing something, and is there a way to do what I want to do?

+8
f #
source share
1 answer

According to MSDN, the colon cannot actually be used in the operator name. This seems to run counter to the F # spec from FSharp.org, I'm not sure what is going on there. But we can check that in FSI:

 > let ( >:> ) ab = a+b Script.fsx(1,7): error FS0035: This construct is deprecated: ':' is not permitted as a character in operator names and is reserved for future use 

If you look at how List<'T> defined , you will find that (::) is actually not a statement, but a constructor case:

 type List<'T> = | ( [] ) | ( :: ) of Head: 'T * Tail: 'T list 

And, of course, you can define your own DU type with a name as the constructor name:

 > type A = > | ( :: ) of string * int > | A of int > > let a = "abc" :: 5 val a : A = Cons ("abc",5) 

Now, oddly enough, if I try to use a different operator-ish-look-name as the case constructor, I get this error:

 > type A = | ( |> ) of string * int Script.fsx(1,14): error FS0053: Discriminated union cases and exception labels must be uppercase identifiers 

This means that (::) is somehow special (and, by the way, this is ([]) ).

So the bottom line is no, you cannot do this.
But why do you need this? Can you possibly agree to a more acceptable operator name that still expresses the semantics of "const" - for example, (<+>) ?

+8
source share

All Articles