2013-08-29 65 views
4

我可以寫我自己的擴展List模塊的OCaml的,通過定義文件lib.ml和包括List模塊:如何延長Map.Make仿

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

爲什麼要限制函數的參數的簽名?你不需要任何with type這裏:

module Make (Ord : Map.OrderedType) = 
struct 
    include Map.Make(Ord) 
    let aaa = 1 
end 

給你一個仿函數Make,鑑於Map.OrderedType實現返回一個模塊的Map.S所有功能,類型key等於Ord.t,和類型的值aaaint

如果您想強制函子的結果堅持某個簽名,那麼您可能確實需要添加類型約束,例如,

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

這樣做是遵循Map.mli的結構,與S模塊後面是製作模塊的正確方式。

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 

希望幫助!