为自定义集合定义cons(::)运算符 [英] Define the cons (::) operator for custom collections
问题描述
我正在使用相当受欢迎的 FSharpx.Collections 包,尤其是 NonEmptyList 类型.
I am using the fairly popular FSharpx.Collections package, and in particular the NonEmptyList type.
此类型提供NonEmptyList.cons
功能,但我想像常规List
(即head :: tail
)一样使用::
运算符.由于tail
必须已经是NonEmptyList<'a>
,所以与List
的::
运算符应该没有任何冲突.
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
导致编译错误:
Unexpected symbol '::' in pattern. Expected ')' or other token.
我知道::
与其他运算符不在同一个类别中,但是我不完全了解操作方式.因此,我或多或少地尝试了一些尝试,例如用op_cons
替换::
之类的方法,但没有成功.
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?
推荐答案
根据到MSDN ,实际上不能在运算符名称中使用冒号.这似乎与FSharp的 F#规范相矛盾. org,我不确定那里发生了什么.但是我们可以在FSI中进行验证:
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
如果您查看 List<'T>
的定义方式,您会发现(::)
实际上不是运算符,而是 case构造函数:
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
当然,您可以定义自己的DU类型,并将其作为构造函数名称:
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).
所以底线似乎是-不,你不能那样做.
但是,为什么您甚至需要?也许您可以选择一个更可接受的运算符名称,该名称仍会表示"cons"的语义-例如(<+>)
?
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, (<+>)
?
这篇关于为自定义集合定义cons(::)运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!