F# discriminated union 语法说明
F# discriminated union syntax clarification
我正在阅读 Expert F# 4.0 并且在某些时候 (p.93) 为 list
引入了以下语法:
type 'T list =
| ([])
| (::) of 'T * 'T list
虽然我从概念上理解这里发生了什么,但我不理解语法。显然你可以把 []
或 ::
放在括号之间,它们意味着一些特殊的东西。
不允许使用其他符号,例如 (++)
或 (||)
。那么这是怎么回事?
另一件事是 (::)
的 'operator' 性质。假设我有以下(奇怪的)类型:
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
完全不同,尽管两者都是有区别的结合。
理论上,F# spec(参见第 8.5 节)表示并集大小写标识符必须是以大写字母开头的字母数字序列。
但是,这种定义列表缺点的方式是 ML 惯用的东西。如果我们被迫写 Cons (x, Cons(y, Cons (z, Empty)))
而不是 x :: y :: z :: []
,街上就会发生骚乱。
因此只有这两个标识符 - ([])
和 (::)
例外。您可以使用这些,但只能使用这两个。除了这两个,只允许大写的字母数字名称。
但是,您可以使用这些有趣的名称定义独立函数:
let (++) a b = a * b
这些函数通常称为“operators”,可以通过中缀表示法调用:
let x = 5 ++ 6 // x = 30
与仅支持前缀表示法的常规函数相反 - 即 f 5 6
.
关于运算符中允许使用哪些字符,哪些只能是一元,哪些只能是二进制,哪些可以是两者,以及它们如何定义结果运算符优先级,有一套单独的非常复杂的规则。请参阅规范的第 4.1 节或 here 以获取完整参考。
我正在阅读 Expert F# 4.0 并且在某些时候 (p.93) 为 list
引入了以下语法:
type 'T list =
| ([])
| (::) of 'T * 'T list
虽然我从概念上理解这里发生了什么,但我不理解语法。显然你可以把 []
或 ::
放在括号之间,它们意味着一些特殊的东西。
不允许使用其他符号,例如 (++)
或 (||)
。那么这是怎么回事?
另一件事是 (::)
的 'operator' 性质。假设我有以下(奇怪的)类型:
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
完全不同,尽管两者都是有区别的结合。
理论上,F# spec(参见第 8.5 节)表示并集大小写标识符必须是以大写字母开头的字母数字序列。
但是,这种定义列表缺点的方式是 ML 惯用的东西。如果我们被迫写 Cons (x, Cons(y, Cons (z, Empty)))
而不是 x :: y :: z :: []
,街上就会发生骚乱。
因此只有这两个标识符 - ([])
和 (::)
例外。您可以使用这些,但只能使用这两个。除了这两个,只允许大写的字母数字名称。
但是,您可以使用这些有趣的名称定义独立函数:
let (++) a b = a * b
这些函数通常称为“operators”,可以通过中缀表示法调用:
let x = 5 ++ 6 // x = 30
与仅支持前缀表示法的常规函数相反 - 即 f 5 6
.
关于运算符中允许使用哪些字符,哪些只能是一元,哪些只能是二进制,哪些可以是两者,以及它们如何定义结果运算符优先级,有一套单独的非常复杂的规则。请参阅规范的第 4.1 节或 here 以获取完整参考。