4

我可以通过定义一个文件并包含模块List来为 OCaml 模块编写自己的扩展:lib.mlList

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

有谁知道该怎么做?

4

2 回答 2

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

于 2013-08-30T06:37:55.687 回答
1

正确的做法是遵循 Map.mli 的结构,一个 S 模块,后跟一个 Make 模块。

我的地图.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

你对“with”约束是正确的,但你把它放在错误的位置。

然后,在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

希望有帮助!

于 2013-08-30T09:43:48.237 回答