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

Ocaml 为什么在一级模块包装中禁用破坏性替换?,ocaml,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 *)

假设:

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]中)之后



为什么我不能在一级模块打包中使用
:=

在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
不允许破坏性替换,因为它创建了一个没有名称的新模块类型。常规替换是可以的,因为类型为t=int的
S仍然是
S
,我们只是对它的定义了解得更多<类型为t:=int
的code>S不是
S
它与
S
有不同的组件,因为它缺少
t
类型

最近(,),一级模块的类型检查已改为结构化,而不是命名:

        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>
OCaml版本4.02.0+dev5-2014-04-29
#模块类型T=sig类型T端;;
模块类型T=sig类型T端
#模块类型S=sig类型t端;;
模块类型S=sig类型t端
#设f(x:(模T)):(模S)=x;;
val f:(模块T)->(模块S)=

这意味着可以为没有名称的类型创建一级模块。但是,这项工作尚未完成,将无法在4.02中提供。因此,在4.02之后的版本中,在一级模块类型中可能确实可以使用破坏性替换。

我说的对吗,您不是在寻找解决方法?只是问一下,我很确定,你知道。也许,在ocaml邮件列表中问这个问题更好?@ivg我不是在要求解决方法,因为
:=
非常方便。一种解决方法是,我只需要一个没有
t
的新签名,然后用
int
替换
t
。我只是想了解他们决定禁用头等舱模块的原因