Ch.11 SML#分割コンパイルシステム

§ 11.3. インターフェイスファイルの構造

インターフェイスファイルは,分割コンパイルするコンパイル単位のイ ンターフェイスを記述したファイルです. インターフェイスファイルの内容は, Require宣言 と Provide宣言 からなります. Require宣言は,コンパイル単位が使用する他のコンパイル単位を 以下の形の宣言として列挙します.

_require smiFilePath

smiFilePathは,他のコンパイル単位のインターフェイスファイル (.smiファイル)です. よく使用されるインターフェイスの集合には,それらをまとめた名前が 付けられ,システムに登録されています. 代表的なものは,The Definition of Standard ML Basis Libraryで実装 が義務付けられている基本ライブラリのインターフェイスファイルをすべて含む basis.smiです. プログラムのインターフェイスファイルの冒頭に

_require "basis.smi";

と書いておくと,基本ライブラリが使用可能となります.

Provide宣言は,コンパイル単位が他のコンパイル単位に提供する SML#の資源を記述します. 記述する資源は,おおよそ,Standard MLのソースファイルの宣言定義 できるものすべてと考えるとよいでしょう. 具体的には,以下のものが含まれます.

  • datatype定義.

  • type定義.

  • exception定義.

  • infix宣言.

  • 変数とその型の定義.

  • モジュールの定義

  • functorの定義

2分探索木のインターフェイスファイルqueue.smiとそのインター フェイスを実装するqueue.smlの例を以下に示します.

queue.smiファイル:

_require "basis.smi"
structure Queue =
struct
  datatype 'a queue = Q of 'a list * 'a list
  exception Dequeue
  val empty : 'a queue
  val isEmpty : 'a queue -> bool
  val enqueue : 'a queue * 'a -> 'a queue
  val dequeue : 'a queue -> 'a queue * 'a
end

queue.smlファイル:

structure Queue =
struct
  datatype 'a queue = Q of 'a list * 'a list
  exception Dequeue
  val empty = Q ([],[])
  fun isEmpty (Q ([],[])) = true
    | isEmpty _ = false
  fun enqueue (Q(Old,New),x) = Q (Old,x::New)}
  fun dequeue (Q (hd::tl,New)) = (Q (tl,New), hd)
    | dequeue (Q ([],_) = raise Dequeue
    | dequeue (Q(Old,New) = dequeue (Q(rev New,[]))
end
Figure 11.2. インターフェイスファイルの例

queue.smiファイルの冒頭に書かれている_require "basis.smi"は,

  • このqueue.smiファイルが基本ライブラリを使うこと,

  • このqueue.smiファイルの中で定義されずに使われている'a listなどの型は,基本ライブラリに定義されていること

を表しています. それ以降の定義がProvide宣言部分です. この例では,このインターフェイスを実装するモジュールがQueueというstructureを提供することを示しています. この例から理解されるとおり,インターフェイスファイルのProvide宣言 はStandard MLのシグネチャと似た構文で記述します. しかしシグネチャと考え方が大きく違うのは,datatypeexceptionなどは仕様ではなく,実体に対応するということです. queue.smiの中で定義されるdatatype 'a queueexception Dequeueは,queue.smlで定義される型および例外そのものと して扱われます. 従って,このqueue.smiを複数のモジュールで_require宣 言を通じて利用しても,queue.smiで定義された同一のものとして扱われ ます.