F#区别联合语法澄清

时间:2016-10-26 19:41:30

标签: syntax f# discriminated-union

我正在阅读Expert F# 4.0并在某个时候(第93页)为list引入了以下语法:

type 'T list =
    | ([])
    | (::) of 'T * 'T list

虽然我从概念上理解这里发生了什么,但我不理解语法。显然,你可以在括号之间放置[]::,它们意味着特别的东西。

不允许使用其他符号,例如(++)(||)。那么这里发生了什么?

另一件事是'运营商' (::)的性质。假设我有以下(奇怪的)类型:

type 'T X =
    | None
    | Some of 'T * 'T X
    | (::) of 'T * 'T X

现在我可以说:

let x: X<string> = Some ("", None)

但不允许这样做:

let x: X<string> = :: ("", None)
let x: X<string> = (::) ("", None)

所以(::)实际上与Some完全不同,尽管两者都是歧视联盟的情况。

1 个答案:

答案 0 :(得分:7)

理论上,F# spec(参见第8.5节)说联合案例标识符必须是以大写字母开头的字母数字序列。

然而,这种定义列表缺点的方式是ML惯用的东西。如果我们被迫写Cons (x, Cons(y, Cons (z, Empty)))而不是x :: y :: z :: [],街上就会发生骚乱。

因此,仅对这两个标识符([])(::)进行了例外处理。你可以使用这些,但只能使用这两个。除了这两个,只允许使用大写的字母数字名称。

但是,您可以使用以下有趣的名称定义独立功能

let (++) a b = a * b

这些函数通常称为“运算符”,可以通过中缀表示法调用:

let x = 5 ++ 6   // x = 30

与仅支持前缀表示法的常规函数​​相反 - 即f 5 6

关于运算符中允许哪些字符有一个单独的非常复杂的规则,它们只能是一元的,它们可以只是二进制,可以是两者,以及它们如何定义结果运算符优先级。请参阅规范的第4.1节或here以获取完整的参考。