dune-ocaml :没有为以下模块提供实现:
dune-ocaml : No implementations provided for the following modules:
我尝试用 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
我该如何解决这个问题?
错误消息抱怨模块 CallccBp
没有实现(也就是没有 ml 文件)。在不知道 CallccBp
的内容的情况下,此模块可能包含异常或扩展构造函数声明(或任何其他类型的运行时组件)。您的第一个修复应该是添加一个 callccBp.ml
文件并删除 (module_without_implementation ...)
行。
看看你对octachron的讨论,让我们从基础开始:
my_module.mli
File where you declare the signatures of your values, modules etc. Not mandatory, I'd advise not using them if you start with OCaml
my_module.ml
File where you implement your values, modules etc. Mandatory since these are the files that make your program run
让我们通过一个玩具项目来看一下:
.
├── 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 "%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"
如果你编译,dune 不应该抱怨,现在你所要做的就是提供一个比 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
中使用 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 older\n"
(if p1.AST.age > p2.AST.age then p1.name else p2.name)
但这在开始时并不是很有用,因为我再次建议不要在开始时接触 mli
个文件
我尝试用 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
我该如何解决这个问题?
错误消息抱怨模块 CallccBp
没有实现(也就是没有 ml 文件)。在不知道 CallccBp
的内容的情况下,此模块可能包含异常或扩展构造函数声明(或任何其他类型的运行时组件)。您的第一个修复应该是添加一个 callccBp.ml
文件并删除 (module_without_implementation ...)
行。
看看你对octachron的讨论,让我们从基础开始:
my_module.mli
File where you declare the signatures of your values, modules etc. Not mandatory, I'd advise not using them if you start with OCaml
my_module.ml
File where you implement your values, modules etc. Mandatory since these are the files that make your program run
让我们通过一个玩具项目来看一下:
.
├── 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 "%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"
如果你编译,dune 不应该抱怨,现在你所要做的就是提供一个比 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
中使用 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 older\n"
(if p1.AST.age > p2.AST.age then p1.name else p2.name)
但这在开始时并不是很有用,因为我再次建议不要在开始时接触 mli
个文件