2013-11-24 71 views
4

有人可以解釋我的仿函數。我想簡單的例子。當我們應該使用函數?OCaml - 仿函數 - 如何使用?

+3

您可以在[ocaml.org上的教程](http://ocaml.org/learn/tutorials/modules.html)和[真實世界OCaml的第9章](https://realworldocaml.org/v1 /en/html/functors.html)。 –

+1

簡單地說,仿函數就像Java中的'interface'。 –

+0

@JacksonTale,呃,沒有。與Java接口最接近的是模塊類型,即使這些類型也有很大不同。與函數最接近的是一個泛型類。 –

回答

3

仿函數本質上是一種根據其他模塊編寫模塊的方法。

一個非常經典的例子是來自標準庫的Map.Make仿函數。這個函數讓你可以定義一個具有特定鍵類型的地圖。

下面是一個簡單的和相當啞例如:

module Color = struct 
    type t = Red | Yellow | Blue | Green | White | Black 

    let compare a b = 
     let int_of_color = function 
      | Red -> 0 
      | Yellow -> 1 
      | Blue -> 2 
      | Green -> 3 
      | White -> 4 
      | Black -> 5 in 
     compare (int_of_color a) (int_of_color b) 
end 

module ColorMap = Map.Make(Color) 

加載這在ocaml示出了所產生的模塊的簽名:

module Color : 
    sig 
    type t = Red | Yellow | Blue | Green | White | Black 
    val compare : t -> t -> int 
    end 
module ColorMap : 
    sig 
    type key = Color.t 
    type 'a t = 'a Map.Make(Color).t 
    val empty : 'a t 
    val is_empty : 'a t -> bool 
    val mem : key -> 'a t -> bool 
    val add : key -> 'a -> 'a t -> 'a t 
    val singleton : key -> 'a -> 'a t 
    val remove : key -> 'a t -> 'a t 
    val merge : 
     (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t 
    val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int 
    val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool 
    val iter : (key -> 'a -> unit) -> 'a t -> unit 
    val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b 
    val for_all : (key -> 'a -> bool) -> 'a t -> bool 
    val exists : (key -> 'a -> bool) -> 'a t -> bool 
    val filter : (key -> 'a -> bool) -> 'a t -> 'a t 
    val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t 
    val cardinal : 'a t -> int 
    val bindings : 'a t -> (key * 'a) list 
    val min_binding : 'a t -> key * 'a 
    val max_binding : 'a t -> key * 'a 
    val choose : 'a t -> key * 'a 
    val split : key -> 'a t -> 'a t * 'a option * 'a t 
    val find : key -> 'a t -> 'a 
    val map : ('a -> 'b) -> 'a t -> 'b t 
    val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t 
    end 

簡單module ColorMap = Map.Make(Color)創造一個實現地圖,其中一個模塊鑰匙是顏色。它現在可以調用ColorMap.singleton Color.Red 1並獲得地圖上紅色的數字1

注意的是,使用Map.Make工作是因爲通過模塊(Color)滿足Map.Make函子的要求。文檔說函子的類型是module Make: functor (Ord : OrderedType) -> S with type key = Ord.t: OrderedType意味着輸入模塊(Color)必須與OrderedType模塊簽名保持一致(我敢肯定還有一個更正式的術語)。

爲了與OrderedType保持一致,輸入模塊必須具有類型t以及帶簽名t -> t -> int的功能compare。換句話說,必須有一種方法來比較t類型的值。如果您查看ocaml報告的類型,這正是Color提供的類型。

何時使用仿函數是一個非常困難的問題,因爲經常有幾種可能的設計,每個都有自己的權衡。但是大多數情況下,當圖書館提供它們作爲推薦的做事方式時,你會使用仿函數。