Define the cons (::) operator for custom collections

青春壹個敷衍的年華 提交于 2020-02-27 22:20:31

问题


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?


回答1:


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, (<+>)?



来源:https://stackoverflow.com/questions/32297544/define-the-cons-operator-for-custom-collections

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!