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

时间:2014-05-08 15:44:01

标签: ocaml

假设这些:

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

module M = struct
  type t = int
  let foo t = t + 1
end

然后我这样做:

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 *)

最重要的是,没问题。


然而,如果我这样做

let z = (module M : Foo with type t := int) (* wrong *)

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

  

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


为什么我无法在头等舱模块包装中使用:=

1 个答案:

答案 0 :(得分: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)

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

# type t = (module sig type t end);;
Characters 17-20:
  type t = (module sig type t end);;
                   ^^^
Error: Syntax error

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

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

        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>

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