2.1 ストラクチャ

モジュールの主目的は、関連する定義(データ型の定義とその型に対する処理)をまとめてパッケージ化し、それらの定義を一貫性のある名前付けの枠組みの元で管理することにあります。これにより名前が不足してしまったり、うっかり間違えてしまいそうな名前が氾濫することを避ける事が出来ます。 そのようなパッケージはストラクチャ(structure)と呼ばれ、任意の定義列を持つ struct ... end という形で導入します。 ストラクチャは通常 module 束縛によって名前を与えられます。 以下には例として、優先度付きキューの型とそれに対する処理をまとめたストラクチャを示します。

#module PrioQueue =
   struct
     type priority = int
     type 'a queue = Empty | Node of priority * 'a * 'a queue * 'a queue
     let empty = Empty
     let rec insert queue prio elt =
       match queue with
         Empty -> Node(prio, elt, Empty, Empty)
       | Node(p, e, left, right) ->
           if prio <= p
           then Node(prio, elt, insert right p e, left)
           else Node(p, e, insert right prio elt, left)
     exception Queue_is_empty
     let rec remove_top = function
         Empty -> raise Queue_is_empty
       | Node(prio, elt, left, Empty) -> left
       | Node(prio, elt, Empty, right) -> right
       | Node(prio, elt, (Node(lprio, lelt, _, _) as left),
                         (Node(rprio, relt, _, _) as right)) ->
           if lprio <= rprio
           then Node(lprio, lelt, remove_top left, right)
           else Node(rprio, relt, left, remove_top right)
     let extract = function
         Empty -> raise Queue_is_empty
       | Node(prio, elt, _, _) as queue -> (prio, elt, remove_top queue)
   end;;
module PrioQueue :
  sig
    type priority = int
    type 'a queue = Empty | Node of priority * 'a * 'a queue * 'a queue
    val empty : 'a queue
    val insert : 'a queue -> priority -> 'a -> 'a queue
    exception Queue_is_empty
    val remove_top : 'a queue -> 'a queue
    val extract : 'a queue -> priority * 'a * 'a queue
  end
    

ストラクチャの外から、その要素を参照するときは「ドット表記」を使います。 ドット表記はストラクチャ名で修飾した識別子です。例えば、文脈から見て値が来るところに PrioQueue.insert とあれば、ストラクチャ PrioQueue の中で定義されている関数 insert を指定したことになります。同様に、文脈から見て型が来るところに PrioQueue.queue とあれば、 PrioQueue の中で定義されている型 queue を指定したことになります。

#PrioQueue.insert PrioQueue.empty 1 "hello";;
- : string PrioQueue.queue =
PrioQueue.Node (1, "hello", PrioQueue.Empty, PrioQueue.Empty)