ocaml - 如何拥有嵌套库?对沙丘等感到困惑

标签 ocaml ocaml-dune

我有一个使用 dune 的 OCaml 项目
按照基本教程中的建议,我有一个目录结构,如:

bin/
    cli.ml
    dune
lib/
    dune
    ...
    <various>.ml
我的 lib 中的文件数dir 正在增长,我想要另一个级别的命名空间。
我想要子目录,例如:
lib/
    utils/
        dune
        ...
        <various>.ml
    some_other_domain/
        dune
        ...
        <various>.ml
    dune
    ...
    <various>.ml
我希望能够像 Lib.Utils.Whatever 一样打开它们
我认为这一定是可能的?
我尝试制作 dune lib/utils 下的文件像:
(library
  (name utils)
  (libraries ...))
...但是 open Lib.Utils.Whatever似乎不起作用。
我找到了 subdir stanza ...但是如果我将其添加到 lib/dune并定义 utils作为子目录 library那么我没有得到命名空间...我必须 open Utils而不是 open Lib.Utils

最佳答案

将它们称为“嵌套库”实际上有点奇怪,因为您想用 Lib.Utils.Whatever 调用它们。 . Utils ,这里是 Lib 的子模块.如果它可以帮助您,这就是我能够做的:

.
├── bin
│   ├── cli.ml
│   └── dune
├── dune-project
├── lib
│   ├── dune
│   ├── lib.ml
│   ├── suba
│   │   └── suba.ml
│   └── subb
│       └── subb.ml
bin/cli.ml
let () =
  Lib.Suba.a ();
  Lib.Subb.b ()
bin/dune
(executable
 (name cli)
 (libraries lib)
)
lib/dune
(include_subdirs unqualified)

(library
 (name lib)
  (modules suba subb)
)
(如果你像这样包含你的模块,你必须使用这些确切的名称,另一种获得控制权的方法是添加以下文件并删除 (modules suba subb) 行:lib/lib.ml
(* here you can give the name you want -- say A -- and use it in bin with Lib.A *)
module Suba = Suba
module Subb = Subb
(总结:
  • 您的dune文件包含 (modules suba subb)
  • 如果子目录包含多个文件,您需要将所有正在使用的文件放入您的(modules ...) 中。节或编译器将无法使用它们

  • lib.ml module MyName = AModule 中应包含您要导出的每个模块的文件(并且只有您要导出的那些)
  • 使用此解决方案,您不想导出的模块不需要显式包含在 lib.ml 中。文件,编译器将在需要时使用它们
    )

  • sub{a|b}/{a|b}.ml
    let {a|b} () = Format.eprintf "{A|B}@."
    
    suba.mlsubb.ml用作 lib 的子模块并且可以与 Lib.Suba.a() 一起使用正如您在 cli.ml 中看到的那样

    请注意,这禁止您为两个文件提供完全相同的名称,因为目录将全部在父目录中展平,因此您不能拥有类似的内容:
    .
    ├── bin
    │   ├── cli.ml
    │   └── dune
    ├── dune-project
    ├── lib
    │   ├── dune
    │   ├── lib.ml
    │   ├── suba
    │   │   └── lib.ml
    │   └── subb
    │       └── lib.ml
    
    因为(include_subdirs unqualified)会让它看起来像
    .
    ├── bin
    │   ├── cli.ml
    │   └── dune
    ├── dune-project
    ├── lib
    │   ├── dune
    │   ├── lib.ml
    │   ├── lib.ml
    |   └── lib.ml
    
    dune将无法知道哪个 lib.ml要使用的文件。

    [编辑] 如果您希望每个库有一个目录,您只需删除 dune lib 根目录下的文件并为每个子目录创建一个:
    .
    ├── bin
    │   ├── cli.ml
    │   └── dune
    ├── dune-project
    ├── lib
    │   ├── suba
    │   │   ├── dune
    │   │   └── suba.ml
    │   └── subb
    │       ├── dune
    │       └── subb.ml
    
    唯一的变化是:bin/cli.ml
    let () =
      Suba.a (); (* no more Lib.(...) *)
      Subb.b ()
    
    bin/dune
    (executable
     (name cli)
     (libraries suba subb)
    )
    
    lib/dune已被删除lib/sub{a|b}/dune
    (library
     (name sub{a|b})
    )
    
    在这种情况下,不同目录中的多个文件可以具有相同的名称。

    关于ocaml - 如何拥有嵌套库?对沙丘等感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67462284/

    相关文章:

    ocaml - 使用 dune 从一组纯文本文件生成可执行的 .ml 测试用例

    functional-programming - 关于OCaml中的模式匹配算法

    ocaml - OCaml/沙丘构建中的未绑定(bind)模块

    macos - 错误 : Version 1. 11 沙丘不受支持

    ocaml - 沙丘 : build library and access it in another project and hide or make inaccessible private or implementation modules

    ocaml - 在 OCaml 中漂亮地打印一个 Hashtbl 以使用 ppx-deriving

    compiler-errors - 为 Windows 64 位编译一致

    types - 模块内的多态类型 (OCaml)

    ocaml - 忽略 OCaml 与 OCamlbuild 的接口(interface)