在 OCaml 4.06 之前,存在一些限制:只能移除最外层级别的类型和模块(不能在子模块内部移除),并且在 with type 的情况下,定义必须是具有相同类型参数的另一个类型构造函数。
析构替换的自然应用是合并共享类型名称的两个签名。
moduletype Printable = sigtype t val print : Format.formatter -> t -> unit endmoduletype Comparable = sigtype t val compare : t -> t -> int endmoduletype PrintableComparable = siginclude Printable include Comparable withtype t := t end
也可以用它来完全移除一个字段
moduletype S = Comparable withtype t := int
moduletype S = sigval compare : int -> int -> int end
或重命名一个字段
moduletype S = sigtype u include Comparable withtype t := u end
moduletype S = sigtype u val compare : u -> u -> int end
请注意,您也可以通过用相同类型进行替换来移除显式类型。
moduletype ComparableInt = Comparable withtype t = int ;;
moduletype ComparableInt = sigtype t = int val compare : t -> t -> int end
moduletype CompareInt = ComparableInt withtype t := int
moduletype CompareInt = sigval compare : int -> int -> int end
moduletype S = sigtype t module Sub : sigtype outer := t type t val to_outer : t -> outer endend
moduletype S = sigtype t module Sub : sigtype t val to_outer : t -> t/2 endend
请注意,与类型声明不同,类型替换声明不是递归的,因此以下替换将被拒绝
#moduletype S = sigtype 'a poly_list := [ `Cons of 'a * 'a poly_list | `Nil ] end ;;
Error: 未绑定类型构造函数 poly_list
局部替换也可以用来为函子应用引入的类型或模块类型提供局部名称
#moduletype F = sigtype set := Set.Make(Int).t moduletype Type = sigtype t endmodule Nest : Type -> sigmoduletype T = Type endmoduletype T := Nest(Int).T val set: set val m : (module T) end;;
moduletype F = sigmoduletype Type = sigtype t endmodule Nest : Type -> sigmoduletype T = Type endval set : Set.Make(Int).t val m : (module Nest(Int).T) end
#moduletype ENDO = sigmoduletype T module F: T -> T endmodule Endo(X: sigmoduletype T end): ENDO withmoduletype T = X.T = structmoduletype T = X.T module F(X:T) = X end;;
moduletype ENDO = sigmoduletype T module F : T -> T endmodule Endo : functor (X : sigmoduletype T end) -> sigmoduletype T = X.T module F : T -> T end
也可以用等效模块类型替换具体模块类型。
moduletype A = sigtype x moduletype R = sigtype a = A of x type b endendmoduletype S = sigtype a = A of int type b endmoduletype B = A withtype x = int andmoduletype R = S
但是,这种替换永远没有必要。
破坏性模块类型替换从签名中删除模块类型替换。
#moduletype ENDO' = ENDO withmoduletype T := ENDO;;