我已经获得了关于OCaml中的仿函数的以下代码:
type comparison = Less | Equal | Greater;;
module type ORDERED_TYPE =
sig
type t
val compare: t -> t -> comparison
end
;;
module Set =
functor (Elt: ORDERED_TYPE) ->
struct
type element = Elt.t
type set = element list
let empty = []
let rec add x s =
match s with
| [] -> [x]
| hd :: tl ->
match Elt.compare x hd with
| Equal -> s
| Less -> x :: s
| Greater -> hd :: add x tl
let rec member x s =
match s with
| [] -> false
| hd :: tl ->
match Elt.compare x hd with
| Equal -> true
| Less -> false
| Greater -> member x tl
end
;;
module OrderedString : ORDERED_TYPE =
struct
type t = string
let compare x y =
if x = y then Equal
else if x < y then Less
else Greater
end
;;
module StringSet = Set(OrderedString);;
let out = StringSet.member "foo" (StringSet.add "foo" StringSet.empty);; (*compile error, where "foo" is expected OrderedString.t but actually is string*)
通过消除: ORDERED_TYPE
module OrderedString : ORDERED_TYPE =
可以避免上述错误
只是无法理解为什么。
类似地,如果模块中有任何类型,如
module A = struct type t = string end;;
如何将字符串值指定为A.t
类型,而不是实际string
感谢。
答案 0 :(得分:4)
您可以在标准库中查看它是如何完成的:set.mli。 仿函数的签名是
module Make (Ord : OrderedType) : S with type elt = Ord.t
with type elt = Ord.t
部分表示elt
类型不是抽象的。
答案 1 :(得分:1)
正如Tomash所提到的,你缺少一个类型约束,但是没有在仿函数签名中(事实上你的代码中没有),但是在你给它的参数中。基本上,当你写
module OrderedString : ORDERED_TYPE = struct ... end
t
中OrderedString
类型的定义将被抽象掉,因为t
是ORDERED_TYPE
签名中的抽象类型。你想要的是OrderedString
确实是ORDERED_TYPE
的实现,但是已知类型为t
。这正是你将得到的
module OrderedString: ORDERED_TYPE with type t = string = struct ... end