如何扩展Map.Make仿函数

时间:2013-08-29 19:56:03

标签: ocaml

我可以通过定义文件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

有谁知道怎么做?

2 个答案:

答案 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

MakeMakeAbstract之间存在一个区别。前者的类型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

希望有所帮助!