假设这些:
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]中)
为什么我不能用于:=头等舱模块包装?
在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之后的版本中,确实可以在第一类模块类型中使用破坏性替换.