使用“with type”时放松类型检查模块构建
我定义了两个模块类型和两个模块
module type FOO = sig type e end
module type BAR = sig type t end
module Foo : FOO = struct type e = int end
module Bar : BAR = struct type t = int end
然后我将一个函子定义为
module Fun (F:FOO) (B:BAR with type t = F.e) = struct type x = string end
(这是一个玩具示例,请忽略函子不使用 F
和 B
的事实)
现在,如果我定义模块
module Bla = Fun (Foo) (Bar)
,我会得到
Error: Signature mismatch:
Modules do not match:
sig type t = Bar.t end
is not included in
sig type t = Foo.e end
Type declarations do not match:
type t = Bar.t
is not included in
type t = Foo.e
虽然 Bar.t
和 Foo.e
都定义为 int
OCaml 认为 Bar .t
和 Foo.e
不同。这就是打字系统的工作方式,考虑到这两种类型总体上不同是有意义的(参见 函子和类型抽象)。
问题:有时我可能希望它通过类型检查,因为就我的目的而言,它们可以被视为相等。有什么办法可以放松这个吗?
使用gasche关于消除强制的建议,上面的代码可以编写为
module type FOO = sig type e end
module type BAR = sig type t end
module Foo = struct type e = int end
module Bar = struct type t = int end
module Fun (F : FOO with type e=int) (B : BAR with type t = int) = struct type x = F.e * B.t end
module Bla = Fun (Foo) (Bar)
可以正常编译的代码。奇怪的是,我得到
# let f x : Bla.x = (x,x);;
val f : Foo.e -> Bla.x = <fun>
问题:为什么它推断出x
是Foo.e
?它也可能是 Bar.t
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题在于如何定义
Foo
和Bar
:module Foo : FOO = ...
。通过在此处施加此签名,您可以“密封”模块并使类型抽象。它无法恢复。您应该在此处删除: FOO
强制转换,并在稍后需要抽象时使用它。您还可以使用模块 Foo : (FOO with type e = int) = ...
。The problem is how you define
Foo
andBar
:module Foo : FOO = ...
. By imposing this signature here, you "seal" the module and make the type abstract. It cannot be reverted. You should remove the: FOO
coercion here, and use it later when you need the abstraction. You could also usemodule Foo : (FOO with type e = int) = ...
.我不确定打印机如何在相同类型中进行选择,但在这种情况下,您可以通过显式注释函数参数来使其打印不同的名称:
I'm not sure how the printer chooses amongst equal types, but in this case you can cause it to print a different name by explicitly annotating your function argument: