我们说我有一个模块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
,以便我无法打开模块A
中的模块C
?
感谢。
答案 0 :(得分:6)
在B
中重新导出内容的一种简单方法是在A
中加入B
:
(* b.ml *)
include A
let string_of_foo = function
| Bar -> "bar"
| Baz -> "baz"
通过使用b.ml
编译此ocamlc -c -i b.ml
,您可以看到发生了什么:
type foo = A.foo = Bar | Baz
val string_of_foo : foo -> string
foo
b.ml
中type foo = A.foo = Bar | Baz
类型的签名可能会让您感到困惑,因为它在OCaml中并不经常出现。它表明类型B.foo
不仅具有相同名称的构造函数,而且与A.foo
完全等效。
从A.foo
重新导出B
的另一种方法是使用此类型定义:
(* 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)
答案 1 :(得分:0)
我现在只学习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)