OCaml使用在仿函数外定义的签名来限制生成模块的可见性
我试图编写一个函数,它需要一对有序的东西并生成另一个有序的东西(按照字典顺序定义)。OCaml使用在仿函数外定义的签名来限制生成模块的可见性
但是,我想要得到的“有序类型”是抽象的,而不是OCaml元组。
这很容易处理内联/匿名签名。
(* orderedPairSetInlineSig.ml *)
module type ORDERED_TYPE = sig
type t
val compare : t -> t -> int
end
module MakeOrderedPairSet (X : ORDERED_TYPE) :
sig
type t
val get_fst : t -> X.t
val get_snd : t -> X.t
val make : X.t -> X.t -> t
val compare : t -> t -> int
end = struct
type t = X.t * X.t
let combine_comparisons fst snd =
if fst = 0 then snd else fst
let compare (x, y) (a, b) =
let cmp = X.compare x a in
let cmp' = X.compare y b in
combine_comparisons cmp cmp'
let get_fst ((x, y) : t) = x
let get_snd ((x, y) : t) = y
let make x y = (x, y)
end
我想给我的匿名签名名称,如ORDERED_PAIR_SET_TYPE
和移动它的MakeOrderedPairSet
的定义之外,像这样(警告:不是语法有效):与el
是一个抽象类型
(* orderedPairSet.ml *)
module type ORDERED_TYPE = sig
type t
val compare : t -> t -> int
end
module type ORDERED_PAIR_SET_TYPE = sig
type t
type el
val get_fst : t -> el
val get_snd : t -> el
val make : el -> el -> t
val compare : t -> t -> int
end
module MakeOrderedPairSet (X : ORDERED_TYPE) :
(ORDERED_PAIR_SET_TYPE with type el = X.t) = struct
type t = X.t * X.t
let combine_comparisons fst snd =
if fst = 0 then snd else fst
let compare (x, y) (a, b) =
let cmp = X.compare x a in
let cmp' = X.compare y b in
combine_comparisons cmp cmp'
let get_fst ((x, y) : t) = x
let get_snd ((x, y) : t) = y
let make x y = (x, y)
end
在我试图绑定到MakeOrderedPairSet
正文内的X.t
的签名中。
但是,我无法弄清楚如何将所有东西放在一起。
(ORDERED_PAIR_SET_TYPE with type el = X.t)
是我能想到的最明显的方式,就是说“给我一个和这个一样的签名,但是用一个抽象类型替换为一个抽象类型(或者在本例中是不同的抽象)”。但是,这种情况在语法上不合法(因为括号)。关闭括号并不会产生有效的“模块语言级表达式”;我把它留下了,因为我认为这让我的意图更加明显。
所以...你如何使用命名的签名来限制[函数产生的模块]/[参数化模块]的可见性?
如果你不希望添加el
到模块的出口则有两种方式:
-
使用替代约束:
ORDERED_PAIR_SET_TYPE with type el := X.t
这将删除的来自签名的
el
规范。 -
使用参数化签名。不幸的是,这是不是在OCaml中直接表达,但需要一些额外的函子体操在你签字的定义:
module SET_TYPE (X : ORDERED_TYPE) = struct module type S = sig type t val get_fst : t -> X.el val get_snd : t -> X.el val make : X.el -> X.el -> t val compare : t -> t -> int end end
有了,你可以写:
module MakeOrderedPairSet (X : ORDERED_TYPE) : SET_TYPE(X).S = ...
为了比较......这是否意味着您可以在不使用包装模块的情况下在SML中编写参数化签名? –
不,SML根本就没有这种能力(尽管一些SML方言可以让你写上类似的东西)。 –
一旦缺乏定义'type el = Xt'固定,你的例子适用于我(有和没有括号)? – octachron
@ octachron yes ...在方法的主体中添加一个明确的'type el = Xt'确实使OCaml程序有效,但它也向接口添加了一个新的导出类型...所以它不完全等效在functor定义之外的第一个例子中“移动”匿名接口。 –