dune-ocaml:没有为以下模块提供任何实现:



我试图用Dune编译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

我该如何解决这个问题?

看看您与octacron的讨论,让我们从基础开始:

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

如果我想在bin/main.ml中使用my_module中的值,我必须:

  • 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 "%dn" 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"

如果您进行编译,dune不应该抱怨,现在您所要做的就是提供一个比failwith "TODO"更有用的实现


如果我们回到我们的玩具项目,看看你为什么想要一个mli文件:

.
├── bin
│   ├── dune
(executable
(name main)
(libraries my_module)
)
│   └── main.ml
let () =
let b = My_module.incr 3 in
Printf.printf "%dn" 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中使用My_module.incr,但不能在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 oldern"
(if p1.AST.age > p2.AST.age then p1.name else p2.name)

但这在开始时并没有真正的用处,因为我再次建议不要在开始的中触摸mli文件

错误消息抱怨模块CallccBp没有实现(也就是没有ml文件(。在不知道CallccBp的内容的情况下,该模块可能包含异常或扩展构造函数声明(或任何其他类型的运行时组件(。您的第一个修复应该是添加一个callccBp.ml文件并删除(module_without_implementation ...)行。

最新更新