我可以通过定义文件List
并包含lib.ml
模块来为OCaml的List
模块编写自己的扩展名:
module List =
struct
include List
(* remove l x returns the list l without the first element x found or *)
(* returns l if no element is equal to x. *)
(* Elements are compared using ( = ). *)
let rec remove (l : 'a list) (x : 'a) : 'a list =
match l with
| [] -> []
| hd :: tl ->
if hd = x then
tl else
hd :: remove tl x
...
end
然后我可以在其他文件中调用Lib.List.remove ...
。
现在我想为Map.Make
仿函数编写自己的扩展,我尝试了lib.ml
中的以下内容:
module Make (Ord : Map.OrderedType with type key = Ord.t) =
struct
include Map.Make(Ord)
let aaa = 1
end
但是,编译会出现错误Error: The signature constrained by 'with' has no component named key
。
有谁知道怎么做?
答案 0 :(得分:2)
为什么要约束函子的参数的签名?您在此处不需要任何with type
:
module Make (Ord : Map.OrderedType) =
struct
include Map.Make(Ord)
let aaa = 1
end
为您提供了一个仿函数Make
,其中Map.OrderedType
的实现会返回一个模块,其中包含Map.S
的所有函数,类型key
等于Ord.t
,以及aaa
类型的值int
。
如果你想强制你的仿函数的结果遵守某个签名,那么你可能确实需要添加类型约束,例如。
module type MyMap = sig include Map.S val aaa: int end
module MakeAbstract (Ord : Map.OrderedType): MyMap with type key = Ord.t =
struct
include Map.Make(Ord)
let aaa = 1
end
Make
和MakeAbstract
之间存在一个区别。前者的类型t
等于MapMake(Ord).t
,而后者的抽象类型为t
答案 1 :(得分:1)
正确的方法是遵循Map.mli的结构,使用S模块,然后是Make模块。
<强> myMap.mli 强>
module type S = sig
include Map.S
val keys: 'a t -> key list
end
module Make (Ord: Map.OrderedType): S with type key = Ord.t
你对“有”约束你是对的,但是你把它放在了错误的位置。
然后,在 myMap.ml :
中module type S = sig
include Map.S
val keys: 'a t -> key list
end
module Make = functor (Ord: Map.OrderedType) -> struct
module Map = Map.Make(Ord)
include Map
let keys m =
Map.fold (fun k _ acc -> k :: acc) m []
end
希望有所帮助!