gpt4 book ai didi

ocaml - 单个 OCaml 模块会导致接口(interface)假设不一致

转载 作者:行者123 更新时间:2023-12-02 04:00:41 35 4
gpt4 key购买 nike

这是我基于 ocamlbuild 的项目结构:

_tags.ml:

true: package(batteries)

Main.mlpack

Stream

主/Stream.ml

module MyStream = BatStream

我正在尝试使用编译Main模块

ocamlbuild -use-ocamlfind Main.cmo

该错误消息对我来说似乎相当不合逻辑:

+ ocamlfind ocamlc -pack Main/Stream.cmo -o Main.cmo
File "_none_", line 1:
Error: The files Main/Stream.cmi and Main/Stream.cmi
make inconsistent assumptions over interface Stream
Command exited with code 2.
Compilation unsuccessful after building 3 targets (0 cached) in 00:00:00

这是使用 OPAM 的 OCaml 4.02.1。

这只发生在与电池链接时,所以我只能认为 Batteries.StreamMain.Stream 之间存在冲突。事实上,如果我添加更多具有依赖项的模块,我可以收到类似的消息

Error: The files /home/ken/.opam/4.02.1/lib/batteries/batteries.cmi
and Main/Stream.cmi make inconsistent assumptions
over interface Stream

但是,我不希望子模块发生冲突。

为什么会发生这种情况?在我看来,模块不可能通过接口(interface)与自身发生冲突。

最佳答案

OCaml 有一个用于编译单元名称的平面命名空间。当编译单元使用某个模块时,它会记录模块接口(interface)的名称和摘要(基本上是接口(interface)的 CRC)。一致性检查确保两个同名的接口(interface)具有相同的摘要(基本上代表相同的实现)。尽管错误消息确实具有误导性,但它仍然是正确的(尽管措辞可以更好)。让我们使用 ocamlobjinfo 工具:

$ ocamlobjinfo _build/Main/Stream.cmi
File _build/Main/Stream.cmi
Unit name: Stream
Interfaces imported:
83d31bf1e61f22b62a8b2728a55f2593 Stream
d0b21ad0c1f4e93fa8c05b9ded519b52 Stream
999b28e3b7638771c87eebf5a8325e42 Pervasives
60c2e7663dd57d13b5920931742e1c10 Format
9642e3ed163e46770985ca668738ed5f CamlinternalFormatBasics
6dc691300ced97c0e319cbcc0a715044 Bytes
3bd1af04573ce2da7fc3dc04403e852e Buffer
383683999ce4d4a54f1689bb92969ecb BatStream
fbefc52bb310bf525973099141e16ffe BatOrd
92bc9ee9d7e3da3421ed7fc5c0ade74d BatInterfaces
7d12ec9e52c91f3af313796ff85158c4 BatInnerIO
6f57ab9f63c2f00619c3ffc9bde0bc80 BatIO
bd48c0243cabeabfa9ba81aa02319882 BatEnum
1972feae99a1525e1b830ca37c4efa20 BatConcurrent

我们导入了两个具有相同名称但不同实现(CRC 和不同)的接口(interface)。第一个接口(interface)实际上是您的 Stream 模块的接口(interface),第二个接口(interface)是标准 Stream 模块的接口(interface):

$ ocamlobjinfo /home/ivg/.opam/devel/lib/ocaml/stream.cmi
File /home/ivg/.opam/devel/lib/ocaml/stream.cmi
Unit name: Stream
Interfaces imported:
d0b21ad0c1f4e93fa8c05b9ded519b52 Stream
999b28e3b7638771c87eebf5a8325e42 Pervasives
9642e3ed163e46770985ca668738ed5f CamlinternalFormatBasics

您可能会注意到每个模块总是导入自己的接口(interface)。因此,冲突发生在您的 Stream 模块和 OCaml 的 Stream 模块之间。标准的 Stream 模块通过 BatStream 模块进入您的编译单元。

总结一下。接口(interface)命名空间是扁平的,因此需要使用前缀来防止冲突,参见BatStream。是的,它很丑。

模块打包可以帮助您防止打包到包中的模块与使用该包的模块之间的名称冲突。例如,如果您有一个模块 M 打包在包 P 中,那么您可以将它与另一个模块 M 链接,并且不会有MP.M 之间存在冲突(如果您所做的一切正确的话)。但是,当您构建包时,构成它的模块不应与它们使用的模块发生冲突,而且不幸的是,OCaml 标准库不是包,因此您应该选择不与标准库冲突的名称或您用于实现包的任何其他库。

关于ocaml - 单个 OCaml 模块会导致接口(interface)假设不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42049798/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com