我试图用沙丘编译一个OCaml代码,但得到了以下错误:
Error: No implementations provided for the following modules:
CallccBp referenced from bin/.CallccTest.eobjs/native/dune__exe__CallccTest.cmx通过执行命令:$ dune build
我的项目层次如下:
callcc/
bin/
callccTest.ml
dune
[
(executable
(name callccTest)
(libraries CallccBp))
]
lib/
CallccBp.mli
dune
[
(library
(name CallccBp)
(modules_without_implementation CallccBp))
]
test/
callccTest.ml
dune [
(test
(name callccTest))
]
callcc.opam
dune-project我该如何解决这个问题?
发布于 2022-04-03 21:56:59
看看您与八时钟的讨论,让我们从基础开始:
my_module.mli
在
文件中声明值、模块等的签名不是强制性的,如果您从OCaml开始,我建议您不要使用它们
my_module.ml
实现值、模块等的
文件是强制性的,因为这些是使程序运行的文件
让我们通过一个玩具项目来看看这个:
.
├── bin
│ ├── dune
(executable
(name main)
)
│ └── main.ml
├── dune-project
├── lib
│ ├── dune
(library
(name my_module)
)
│ └── my_module.ml
└── program.opam如果我想在my_module中使用bin/main.ml中的值,我必须:
my_module.ml
bin/dune文件中的(libraries my_module)节,My_module.<name_of_value>一起使用
这看起来是:
.
├── bin
│ ├── dune
(executable
(name main)
(libraries my_module)
)
│ └── main.ml
let () =
let b = My_module.incr 3 in
Printf.printf "%d\n" b
├── dune-project
├── lib
│ ├── dune
│ └── my_module.ml
let incr a = a + 1
└── program.opam现在,让我们回到您的层次结构:
callcc/
bin/
callccTest.ml
dune
[
(executable
(name callccTest)
(libraries CallccBp))
]
lib/
CallccBp.mli
dune
[
(library
(name CallccBp)
(modules_without_implementation CallccBp))
]
test/
callccTest.ml
dune [
(test
(name callccTest))
]
callcc.opam
dune-project一切看起来都很好,除了CallccBp.mli只是一个接口,而不是一个实现。首先,您可以删除该文件,创建包含以下两个函数的CallccBp.ml:
CallccBp.ml
let callcc = failwith "TODO"
let throw = failwith "TODO"如果你编译,沙丘不应该抱怨,现在你要做的就是提供一个比failwith "TODO"更有用的实现
如果我们回到我们的玩具项目,看看为什么您想要一个mli文件:
.
├── bin
│ ├── dune
(executable
(name main)
(libraries my_module)
)
│ └── main.ml
let () =
let b = My_module.incr 3 in
Printf.printf "%d\n" b
├── dune-project
├── lib
│ ├── dune
│ └── my_module.ml
let dummy _ = failwith "USELESS"
let incr a = a + 1
│ └── my_module.mli
val incr : int -> int
(** [incr d] will return [d] incremented by 1. Highly efficient. Trust me. *)
└── program.opam我将能够在bin/main.ml中使用bin/main.ml,但不能使用My_module.dummy,因为mli文件没有显示它,因此不能在my_module.ml之外访问它。另外,对于一个库用户来说,my_module.mli文件是一个入口点,用户不想知道它是如何实现的,而只是想使用它,知道可用的值、它们的类型,以及它们通常从注释中做什么。
modules_without_implementation节用于不需要实现的mli文件,即类型声明文件,因此模块如下所示:
AST.mli
type ('a, 'b) res = Ok of 'a | Error of 'b
type num = Int of int | Float of float
type person = {id : int; name : string; age : num}您可以在其他文件中使用它们,如下所示:
file.ml
type t = {player1 : AST.person; player2 : AST.person}
let whos_older p1 p2 =
Printf.printf "%s is older\n"
(if p1.AST.age > p2.AST.age then p1.name else p2.name)但是,当开始时,这并不是真正有用的,因为,再一次,我建议不要在开始时接触mli文件
发布于 2022-04-03 10:30:54
错误消息是抱怨模块CallccBp没有实现(也就是没有ml文件)。在不了解CallccBp的内容的情况下,该模块很可能包含异常或扩展构造函数声明(或任何其他类型的运行时组件)。您的第一个修复应该是添加一个callccBp.ml文件并删除(module_without_implementation ...)行。
https://stackoverflow.com/questions/71724506
复制相似问题