プログラミング言語SML#解説 4.1.0版
14 SML#の拡張機能:SML#分割コンパイルシステム

14.4 型の隠蔽

前節の例から理解されるとおり,インターフェイスファイルの基本的考え 方は,以下のとおりです.

  1. 1.

    datatypeexceptionなどのコンパイル時に定義される資源 (静的資源)は,将来そのインターフェイスファイルで定義される実体そのものを 記述する.

  2. 2.

    関数や変数などの実行時の値を表すものは,その型のみを宣言する.

これら情報が,コンパイラがこのインターフェイスファイルを使う別のソー スコードをコンパイルする上で必要かつ十分な情報です. しかし,この原則だけでは,Standard MLのモジュールシステムが提供 する型情報の隠蔽の機能を使うことができません. 例えば,前節のインターフェイスファイルqueue.smiでは,’a queueの実装が,Q of ’a list * ’a listと定義され公開されていま すが,この実装の詳細は隠蔽したい場合が多いと思われます.

この問題の解決のために,インタフェイスファイルに

type tyvars tyid (= typeRep)    (* 括弧はそのまま記述する *)
eqtype tyvars tyid (= typeRep)    (* 括弧はそのまま記述する *)

の形の隠蔽された型の宣言を許しています. この宣言は,型tyidが定義されその実装の表現はtypeRepであるが, その内容はこのインターフェイスの利用者からは隠されることを表しています. シグネチャ同様,type宣言は,同一性判定を許さない型,eqtypeは同一性判定が可能な型を表します. typeRepには, tyidを実装する型の型コンストラクタを指定します. 例えば,

type t1 = int
type t2 = int list
type ’a t3 = (’a * ’a) array

という実装に対して,インターフェースファイルは

type t1 (= int)
type t2 (= list)
type ’a t3 (= array)

と書きます. 実装型がレコード型,組型,関数型ならば, typeRepにはそれぞれ{}*->を指定します. 実装型がdatatypeで定義された型ならば,コンストラクタの 定義に応じて以下のいずれかを指定します.

  • unit. 引数を持たないコンストラクタだけからなり,かつコンストラクタが 1つしか存在しない.

  • contag. 引数を持たないコンストラクタだけからなり,かつコンストラクタが2つ 以上存在する.

  • boxed. 上記のいずれにも当てはまらない.

例えば,queue.smidatatype ’a queue宣言のかわりに

type ’a queue (= boxed)

と書くことができます.

さらに,シグネチャの場合同様,インターフェイスファイルは,そのイン ターフェイスを実装するソースが定義する変数をすべて網羅している必要はありま せん. インターフェイスに宣言されたもののみが,そのインターフェイスを_require宣言を通じて利用するユーザに見えるようになります.