2013-07-22 20 views
3

我已經得到有關OCaml中的仿函數後續代碼:如何投放類型的函子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_TYPEmodule OrderedString : ORDERED_TYPE =

正好可以」不明白爲什麼。

類似地,如果有我怎麼可以指定一個字符串值作爲類型A.t但不是實際的string

感謝任何類型的模塊中像

module A = struct type t = string end;; 

+0

讓我發現這個讀書有用,因爲我無法弄清楚發生了什麼事有http://stackoverflow.com/questions/9778595/ocaml-functors-counter-intuitive-行爲。 – snf

回答

4

你可以看看它是如何在標準庫中完成的:set.mli。 仿函數的簽名是

module Make (Ord : OrderedType) : S with type elt = Ord.t 

with type elt = Ord.t部分指出elt類型不是抽象。

1

正如Tomash所提到的那樣,您缺少類型約束,但不在函子簽名中(實際上在代碼中沒有任何代碼),而是在您給它的參數中。基本上,當你寫

module OrderedString : ORDERED_TYPE = struct ... end 

類型tOrderedString會被抽象掉的定義,因爲t是在ORDERED_TYPE簽名抽象類型。你在這裏想要說的是,OrderedString確實是ORDERED_TYPE的實現,但是具有已知類型t。這正是你會

module OrderedString: ORDERED_TYPE with type t = string = struct ... end