I am using the fairly popular FSharpx.Collections package, and in particular the NonEmptyList type.
This type provides the NonEmptyList.cons
function, but I want to use the ::
operator as with regular List
, i.e. head :: tail
. Since tail
must already be a NonEmptyList<'a>
, there shouldn't be any conflict with List
's ::
operator.
However, it seems I cannot define the operator. This:
let ( :: ) h t = NonEmptyList.cons h t
results in a compilation error:
Unexpected symbol '::' in pattern. Expected ')' or other token.
I know that ::
is not quite in the same category as other operators, but I don't fully understand how. So I tried a few things more or less at random, such as replacing ::
with op_cons
and the like, without success.
Am I missing something, and is there a way to do what I want to do?
According to MSDN, colon cannot actually be used in operator name. This seems to contradict the F# specification from FSharp.org, I'm not sure what's going on there. But we can verify that in FSI:
> let ( >:> ) a b = 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>
is defined, you'll find that (::)
is not actually an operator, but a case constructor:
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
And sure enough, you can define your own DU type with that as constructor name:
> type A =
> | ( :: ) of string * int
> | A of int
>
> let a = "abc" :: 5
val a : A = Cons ("abc",5)
Now, oddly, if I try to use another operator-ish-looking name as 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
Which means that (::)
is somehow special (and so is ([])
, by the way).
So the bottom line seems to be - no, you can't do that.
But why do you even need to? Can you, perhaps, settle for a more acceptable operator name, which would still express the semantics of "cons" - like, say, (<+>)
?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With