什么时候重新声明模块与别名?

when are modules redeclared vs aliased?

我很难理解 OCaml 中模块和类型是别名还是重新声明。

例如,要在文件中使用模块 A x.ml 似乎我有几个路径:

我是不是漏掉了什么?

open A 中什么都不是 defined or declared,这个 模块表达式 只允许您使用打开的模块中的元素而不引用模块名称。这是一个纯命名空间操作,在运行时没有反映。换句话说,它只影响打字环境。

module A = X.A 中,您正在定义(自 4.02 起)模块别名。因此,无需重新声明任何内容,并且 A 及其所有组件都可以在预期 X.A 及其组件的同一位置使用。

ppx_open 扩展使您可以更好地控制要在当前模块中添加别名的内容。最后,它重写为

open struct 
  type t = Other.t
  module Foo = Other.Foo
  let foo = Other.foo
end

所以它仍然是一个 open 表达式,没有任何重新定义。

最后一个示例 module B with A := A 不是有效的模块表达式。

Am I missing something?

我认为您遗漏了有关共享限制 的信息。这才是最重要的,例如,

module type X = sig type t val x end
module Foo : X = struct type t = int let x = 42 end
module Bar = Foo (* [Bar.x; Foo.x] typechecks *)
module Bar : X = Foo (* [Bar.x; Foo.x] no longer typechecks, they have distinct types *)
module Bar = struct include Foo end (* [Bar.x; Foo.x] .. typechecks *)
module Bar : sig include module type of Foo end = struct include Foo end 
(* [Bar.x; Foo.x] doesn't typecheck *)

正如你从上面的例子中看到的,如果你没有指定签名,OCaml 会尝试赋予 the strongest 可能的签名,唯一的例外是 module type of,它明确地阻止了签名加强,即产生未加强的签名。这并不意味着它将删除别名,例如,

# module X = struct type t = int let x = 42 end;;
module X : sig type t = int val x : int end
# module type X_of_X = module type of X;;
module type X_of_X = sig type t = int val x : int end

注意aliasing信息并没有被抹掉,但是并没有被强化为type t = int = X.t,但是也没有必要,因为X.tY.t的类型是已知的相等,因为它们是同一类型的别名,例如,

# module Y : sig include module type of X end = X;;
module Y : sig type t = int val x : int end
# [X.x; Y.x];;
- : int list = [42; 42]