代码之家  ›  专栏  ›  技术社区  ›  Jack

OCaml类型声明中的冗余(ml/mli)

  •  32
  • Jack  · 技术社区  · 14 年前

    我试图了解有关ocaml模块及其编译的一个具体内容:

    我是否被迫重新声明 .mli 在特定的 .ml

    举个例子:

    (* foo.mli *)
    type foobar = Bool of bool | Float of float | Int of int
    
    (* foo.ml *)
    type baz = foobar option
    

    错误:未绑定类型构造函数foobar

    在尝试用编译时

    ocamlc -c foo.mli
    ocamlc -c foo.ml
    

    foobar 里面 foo.ml 但这似乎是一个复杂的方式,因为我必须保持同步的每一个变化。

    有没有办法避免这种冗余,或者我每次都被迫重新声明类型?

    5 回复  |  直到 14 年前
        1
  •  18
  •   Catherine    10 年前

    OCaml试图强制您分离接口( .mli .ml . 大多数时候,这是一件好事;对于值,在接口中发布类型,并将代码保留在实现中。您可以说OCaml正在强制执行一定量的抽象(必须发布接口;接口中没有代码)。

    对于类型,实现通常与接口相同:两者都声明类型具有特定的表示(可能类型声明是生成的)。在这里,不可能有抽象,因为实现者没有任何关于他不想发布的类型的信息(例外情况基本上是在声明抽象类型时。)

    type foobar = Bool of bool | Float of float | Int of int ,只有一种可能的实现。所以不要写实现!

    一个常见的习惯用法是有一个专用于类型声明的模块,并使它只有一个 mli先生 . 因为类型不依赖于值,所以这个模块通常在依赖链的早期出现。大多数编译工具都能很好地处理这个问题;例如 ocamldep 会做正确的事(这是一个比只有一个 .)

    foo ,然后是 OrderedFoo : Map.OrderedType 带的模块 type t = foo ,然后是另一个类型声明,涉及 'a Map.Make(OrderedFoo).t types1.mli ),然后是一个模块( mod1.mli mod1.ml ),然后是更多类型( types2.mli .毫升 或者复制。

        2
  •  18
  •   Norman Ramsey    14 年前

    • 不要使用.mli文件;把所有东西都暴露出来,没有接口。糟糕的主意。

    对于小型项目,我们只是复制类型声明。并为此发牢骚。

        3
  •  15
  •   aneccodeal    14 年前

    ocamlc -i some.ml > some.mli
    
        4
  •  3
  •   Michael Ekstrand    14 年前

    一般来说,是的,您需要复制这些类型。

    不过,您可以使用Camlp4和 pa_macro 语法扩展(findlib包: camlp4.macro ). 除其他外,它定义并包括构造。您可以使用它将公共类型定义分解到一个单独的文件中,并将该文件包含在两个文件中 .ml .mli 文件夹。但是,我还没有在已部署的OCaml项目中看到这样做,所以我不知道它是否符合推荐的做法,但这是可能的。

    不过,有文化的编程解决方案更干净。

        5
  •  -3
  •   dsgbdg    14 年前