2.3 ファンクタ

ファンクタはストラクチャからストラクチャへの「関数」であり、パラメータ化されたストラクチャを表現するために使用されます。 例えば、ストラクチャ B によりパラメータ化された ストラクチャ A は、単純に仮引数 B (ストラクチャ B のシグネチャを持つことが期待される) を持ち、実際のファンクタ A を返すファンクタ F として表現されます。 そのようなファンクタ F があるとき、 F に対していくつかの B の実装 B1 ... Bn を適用することで、対応するストラクチャ A1 ... An が得られます。

具体的な例として、ソート済リストとして実装した集合を考えます。 ここで考える集合は集合要素の型と、集合要素の型の上の順序付け関数でパラメータ化されています。

#type comparison = Less | Equal | Greater;;
type comparison = Less | Equal | Greater

#module type ORDERED_TYPE =
   sig
     type t
     val compare: t -> t -> comparison
   end;;
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         (* x is already in s *)
            | Less    -> x :: s    (* x is smaller than all elements of 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     (* x belongs to s *)
             | Less    -> false    (* x is smaller than all elements of s *)
             | Greater -> member x tl
     end;;
module Set :
  functor (Elt : ORDERED_TYPE) ->
    sig
      type element = Elt.t
      type set = element list
      val empty : 'a list
      val add : Elt.t -> Elt.t list -> Elt.t list
      val member : Elt.t -> Elt.t list -> bool
    end
    

このように定義したファンクタ SetORDERED_TYPE を実装したストラクチャに適用することにより、その型に対する集合演算を得ることが出来ます。

#module OrderedString =
   struct
     type t = string
     let compare x y = if x = y then Equal else if x < y then Less else Greater
   end;;
module OrderedString :
  sig type t = string val compare : 'a -> 'a -> comparison end

#module StringSet = Set(OrderedString);;
module StringSet :
  sig
    type element = OrderedString.t
    type set = element list
    val empty : 'a list
    val add : OrderedString.t -> OrderedString.t list -> OrderedString.t list
    val member : OrderedString.t -> OrderedString.t list -> bool
  end

#StringSet.member "bar" (StringSet.add "foo" StringSet.empty);;
- : bool = false