# type foo = Foo of int * int
# let t = (1, 2)
# Foo t
Error: The constructor Foo expects 2 argument(s),
but is applied here to 1 argument(s)
Run Code Online (Sandbox Code Playgroud)
它是如何,我必须这样做Foo (1, 2),以避免错误甚至牛逼有合适的类型?
Jef*_*eld 12
在我看来,这是OCaml语法的一个令人不安的部分.尽管它看起来很像,但构造函数Foo不需要2元组作为其参数.从语法上讲,它在括号中需要两个值 - 但它们不是元组.所以它只是t具有错误类型的情况.做这项工作的方法是说:
let (a, b) = t in Foo (a, b)
Run Code Online (Sandbox Code Playgroud)
问题实际上是括号被用于两个不同的事情(或者我声称).一旦你习惯了这一点,处理就不那么困难了.
编辑:如果您希望构造函数Foo采用单个元组,而不是两个单独的值,您可以像这样定义它:
type foo = Foo of (int * int)
Run Code Online (Sandbox Code Playgroud)
然后原始代码的其余部分将起作用.
需要注意的是区分Foo of (a * b)和Foo of a * b有出于效率的考虑:Foo of (a * b)具有参数,它是一个元组,一个指向在堆中的两个元素.Foo of a * b有两个参数直接用标签打包,避免了间接.
这也是为什么,例如,使用关联列表的算法(例如带链接列表桶的Hashtables)有时会定义自己的数据类型而不是重用('a * 'b) list:
type ('a, 'b) assoc_list =
| Nil
| Cons of 'a * 'b * ('a, 'b) assoc_list
Run Code Online (Sandbox Code Playgroud)
当然,在一般的高级别情况下,这种专业化并不是非常重要(并且可能会阻碍代码重用),但是当您真正需要更严格地控制内存表示时,能够了解这些技术细节仍然很好.