什么时候重新声明模块与别名?
when are modules redeclared vs aliased?
我很难理解 OCaml 中模块和类型是别名还是重新声明。
例如,要在文件中使用模块 A x.ml
似乎我有几个路径:
open X.A
,不太好,因为我打开了所有东西
module A = X.A
,我在这里重新声明了吗?这会产生各种问题吗?
- 用https://github.com/johnyob/ppx-open来个铁锈味的
use X::A
module B with A := A
破坏性的模块替换,但这样做我失去了对模块 A 的访问权限
我是不是漏掉了什么?
在 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.t
和Y.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]
我很难理解 OCaml 中模块和类型是别名还是重新声明。
例如,要在文件中使用模块 A x.ml
似乎我有几个路径:
open X.A
,不太好,因为我打开了所有东西module A = X.A
,我在这里重新声明了吗?这会产生各种问题吗?- 用https://github.com/johnyob/ppx-open来个铁锈味的
use X::A
module B with A := A
破坏性的模块替换,但这样做我失去了对模块 A 的访问权限
我是不是漏掉了什么?
在 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.t
和Y.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]