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 ...)линия.

Другие вопросы по тегам