为什么在一流的模块包装中禁用破坏性替换?

Jac*_*ale 9 ocaml

假设这些:

module type Foo = sig
  type t
  val foo : t -> t
end

module M = struct
  type t = int
  let foo t = t + 1
end
Run Code Online (Sandbox Code Playgroud)

然后我做:

module type Goo = Foo with type t = int

module type Hoo = Foo with type t := int

let x = (module M : Goo) (* correct *)

let y = (module M : Hoo) (* correct *)

let z = (module M : Foo with type t = int) (* correct *)
Run Code Online (Sandbox Code Playgroud)

最重要的是,没问题.


但是,如果我这样做

let z = (module M : Foo with type t := int) (* wrong *)
Run Code Online (Sandbox Code Playgroud)

这是错误的,并给出了错误

错误:解析错误:[ident]之后预期的"="(在[package_type_cstr]中)


为什么我不能用于:=头等舱模块包装?

Leo*_*ite 8

在OCaml 4.01及更早版本中,第一类模块是名义上的类型.换句话说,它们的类型基于所使用的模块类型的名称,而不是其结构.例如:

        OCaml version 4.01.0

# module type T = sig type t end;;
module type T = sig type t end
# module type S = sig type t end;;
module type S = sig type t end
# let f (x : (module T)) : (module S) = x;;
Characters 38-39:
  let f (x : (module T)) : (module S) = x;;
                                        ^
Error: This expression has type (module T)
       but an expression was expected of type (module S)
Run Code Online (Sandbox Code Playgroud)

这要求模块类型具有名称:

# type t = (module sig type t end);;
Characters 17-20:
  type t = (module sig type t end);;
                   ^^^
Error: Syntax error
Run Code Online (Sandbox Code Playgroud)

不允许破坏性替换,因为它创建了一个没有名称的新模块类型.定期替换很好,因为S with type t = int,仍然是S,我们只是更多地了解它的定义.因为它没有类型,所以它S with type t := int不S具有不同的组件.St

最近(Mantis,SVN),对一流模块的类型检查已经改为结构而不是主格:

        OCaml version 4.02.0+dev5-2014-04-29

# module type T = sig type t end;;
module type T = sig type t end
# module type S = sig type t end;;
module type S = sig type t end
# let f (x : (module T)) : (module S) = x;;
val f : (module T) -> (module S) = <fun>
Run Code Online (Sandbox Code Playgroud)

这意味着可以为没有名称的类型创建第一类模块.但是,这还没有完成,将不会在4.02中提供.因此,在4.02之后的版本中,确实可以在第一类模块类型中使用破坏性替换.