在定义它们的模块外部使用开放联合
为什么这个效果很好?
module Account = struct
type account_type = Current of float | Savings of float
end
let sarah = Account.Current 100.0;;
下面的最后一行会产生 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
时都必须打开模块?
预先感谢,
扎克
Why does this work fine?
module Account = struct
type account_type = Current of float | Savings of float
end
let sarah = Account.Current 100.0;;
While the final line in the following produces an 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;;
That is, why can't I use the open union type outside the module without opening the module? I should say I've found out that changing the final line to:
open Account;;
let pete = `Current 100.0;;
works fine, but obviously this is cumbersome if I use account_type
a lot, or alternatively I have to open Account
at the start of any code section where account_type
is used, which means I'd sacrifice the abstraction I'd get by using a signature for Account
I've trawled through several OCaml tutorials as well as the INRIA documentation, and I can't find any mention of how you do this.
Is it possible to avoid having to open the module every time I want to use an account_type
?
Thanks in advance,
Zach
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在第二个示例中,您实际上根本不必
开设帐户
,语法只是`Current 100.0
。多态变体标签不参与任何特定类型。`Current
的类型是[> `Current ]
,这(>
)意味着该类型至少是`Current
,并且因为它是函数接受的类型的子集,它会编译得很好。您可以将相同的值传递给多个接受同名多态变体的函数。当然,缺少静态类型信息,输入错误和情况可能会变得相当复杂。通过多态变体进行代码重用讨论了一些优点和他们的用例。
In the second example, you actually don't have to
open Account
at all, the syntax is just`Current 100.0
. A Polymorphic variant tag does not participate in any particular type. The type of`Current
is[> `Current ]
, this (the>
) means the type is at least`Current
, and since that is a subset of the type accepted by the function, it will compile just fine. You can pass that same value to a number of functions that accept a polymorphic variant of the same name. Of course, there is a lack of static type information, and typing errors and situations can become quite complex.Code Reuse through polymorphic variants talks about some advantages and use cases for them.
像
`Current
这样的多态变体常量是全局定义的,类似于整数常量。您不会说Account.10
来引用Account
模块内的整数 10。这是多态变体的优点(和缺点),您可以在不定义它们的情况下使用它们(就像在使用它之前不必定义 10 一样)。
因此,正如 nlucaroni 所说,您不必打开
Account
模块即可访问`Current
。与整数不同,多态变体也可以带参数(如
`Current 100.0
中所示)。但参数的数量及其类型并不固定,甚至对于代码中不同位置的同一构造函数,参数的数量和类型可能会有所不同。因此,nlucaroni 也提到了复杂性。[格式说明:要使单反引号
`
显示在打字机样式的文本中,Markdown 约定是使用双反引号将文本括起来。这会在文本中留下单反引号。或者至少它对我有用。]The polymorphic variant constants like
`Current
are globally defined, similarly to integer constants. You wouldn't sayAccount.10
to reference the integer 10 inside theAccount
module.This is the strength (and weakness) of polymorphic variants, you can use them without defining them (like you don't have to define 10 before using it).
So, as nlucaroni says, you don't have to open the
Account
module to get access to`Current
.Unlike the integers, polymorphic variants can also take parameters (as in your
`Current 100.0
). But the number of parameters and their types aren't fixed, and they can even vary for the same constructor in different places in the code. Hence the complexities also mentioned by nlucaroni.[Formatting note: to get single backquotes
`
to show up in typewriter-styled text, the markdown convention is to use doubled backquotes to enclose the text. This leaves single backquotes alone inside the text. Or at least it's working for me.]