如何在 OCaml 中重新导出一个类型?

How a reexport a type in OCaml?

假设我有一个模块 A 定义如下:

type foo = Bar | Baz

一个模块B:

open A

let string_of_foo = function
    | Bar -> "bar"
    | Baz -> "baz"

和一个模块 C:

open A
open B

let () =
    let f = Bar in
    print_endline (string_of_foo f)

如何更改模块 B 以重新导出类型 foo,这样我就不必在模块 C 中打开模块 A

谢谢。

我现在才学习 OCaml 3 个月,所以我的答案可能不是最好的。但是根据我开始阅读的书:Real World OCaml 打开很多模块不是一个好主意。在你的情况下,我会使用点符号:

一个模块B:

let string_of_foo = function
  | A.Bar -> "bar"
  | A.Baz -> "baz"

实际上,只需要首先 A. 就可以告诉 OCaml 您想要什么类型。这个也应该有效:

let string_of_foo = function
  | A.Bar -> "bar"
  | Baz -> "baz"

但我更喜欢保持一致。

和一个模块 C:

let () =
  let f = A.Bar in
  print_endline (B.string_of_foo f)

B 中重新导出内容的一种简单方法是将 A 包含在 B 中:

(* b.ml *)
include A

let string_of_foo = function
| Bar -> "bar"
| Baz -> "baz"

通过使用 ocamlc -c -i b.ml 编译此 b.ml,您可以看到发生了什么:

type foo = A.foo = Bar | Baz
val string_of_foo : foo -> string

b.mltype foo = A.foo = Bar | Bazfoo 类型的签名可能会让您感到困惑,因为它在 OCaml 中并不常见。它表明类型 B.foo 不仅具有相同名称的构造函数,而且与 A.foo.

完全等价

B 重新导出 A.foo 的另一种方法是使用此类型定义:

(* b.ml *)
type foo = A.foo = Bar | Baz

let string_of_foo = function
  | Bar -> "bar"
  | Baz -> "baz"   

当您只想重新公开模块中定义的某些类型时,这很有用。 (include A 重新导出 A 中定义的所有内容。)

不要忘记写 = A.foo,否则 B.foo 会变成与 A.foo 不同的类型,即使它们具有相同的名称。

通过其中一项更改,您可以编写 C 而无需直接引用 A

open B

let () =
    let f = Bar in
    print_endline (string_of_foo f)