为什么这样可以正常使用?
module Account = struct
type account_type = Current of float | Savings of float
end
let sarah = Account.Current 100.0;;
虽然下面的最后一行产生Error: syntax error
?
module Account = struct
type 'a account_type = [> `Current of float | `Savings of float ] as 'a
end
let pete = Account.`Current 100.0;;
也就是说,为什么我不能在不打开模块的情况下在模块外部使用open union类型?我应该说我发现将最后一行更改为:
open Account;;
let pete = `Current 100.0;;
工作正常,但是如果我经常使用account_type
这很麻烦,或者我必须在使用Account
的任何代码部分的开头打开account_type
,意味着我会通过使用Account
的签名来牺牲我得到的抽象
我已经浏览了几个OCaml教程以及INRIA文档,我找不到你如何做到这一点。
是否可以避免每次我想使用account_type
时打开模块?
提前致谢,
扎克
答案 0 :(得分:6)
在第二个示例中,您实际上根本不需要open Account
,语法只是`Current 100.0
。多态变体标签不参与任何特定类型。 `Current
的类型为[> `Current ]
,此(>
)表示类型至少为`Current
,因为这是函数接受的类型的子集,它会编译得很好。您可以将相同的值传递给许多接受同名多态变体的函数。当然,缺少静态类型信息,键入错误和情况可能会变得非常复杂。
Code Reuse through polymorphic variants讨论了它们的一些优点和用例。
答案 1 :(得分:5)
像`Current
这样的多态变体常量是全局定义的,类似于整数常量。你不会说Account.10
引用Account
模块中的整数10。
这是多态变体的强度(和弱点),您可以在不定义它们的情况下使用它们(就像在使用它之前不必定义10)。
因此,正如nlucaroni所说,您无需打开Account
模块即可访问`Current
。
与整数不同,多态变体也可以采用参数(如`Current 100.0
中所示)。但是参数的数量和它们的类型并不固定,它们甚至可以在代码中的不同位置对于相同的构造函数而变化。因此nlucaroni也提到了复杂性。
[格式化注释:要使单个反引号`
显示在打字机样式的文本中,降价约定是使用加倍的反引号来包含文本。这会在文本中留下单个反引号。或者至少它对我有用。]