dune-ocaml : Для следующих модулей не предусмотрено реализации:
Я попытался скомпилировать код OCaml с помощью Dune, но получил следующую ошибку:
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
Как я могу решить эту проблему?
2 ответа
Глядя на вашу дискуссию с октахроном, давайте начнем с основ:
Файл, в котором вы объявляете подписи ваших значений, модулей и т. д. Не обязательно, я бы посоветовал не использовать их, если вы начинаете с OCaml.
Файл, в котором вы реализуете свои значения, модули и т. д. Обязателен, так как это файлы, которые запускают вашу программу.
Давайте посмотрим на это с игрушечным проектом:
.
├── bin
│ ├── dune
(executable
(name main)
)
│ └── main.ml
├── dune-project
├── lib
│ ├── dune
(library
(name my_module)
)
│ └── my_module.ml
└── program.opam
Если я хочу использовать значения из
my_module
в , я должен:
- иметь значения в
- добавить
(libraries my_module)
строфа в моемbin/dune
файл - использовать эти значения с
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
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
я смогу использовать
My_module.incr
в
bin/main.ml
но нет
My_module.dummy
потому что он не отображается файлом и, следовательно, недоступен за пределами
my_module.ml
. И в качестве бонуса,
my_module.mli
файл является точкой входа для пользователя библиотеки, который не хочет знать, как она реализована, а просто хочет использовать ее, зная доступные значения, их типы и, часто, то, что они делают из комментария.
В
modules_without_implementation
Раздел предназначен для файлов, которые не нуждаются в реализации, а именно для файлов объявлений типов, поэтому модули выглядят следующим образом:
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
файлы в начале
Сообщение об ошибке жалуется, что для модуля нет реализации (или файла мл). Не зная содержания
CallccBp
, вполне вероятно, что этот модуль содержит либо исключение, либо объявление конструктора расширения (или любые другие компоненты среды выполнения). Ваше первое исправление должно состоять в том, чтобы добавить
callccBp.ml
файл и удалить
(module_without_implementation ...)
линия.