: 再帰的データ型 : 型推論 : 陰に型付けされた多相言語
Generalization と instantiation
- function を変換する場合,自由メタ変数を持つ型 で終了する.型 は のようになる. は, からは instantiate しないとする.
- そのような場合は,以下のように generalize する.
そのため,関数 はすべての型を適用することができる.
- しかし,注意が必要である.以下のプログラムを考えよう.
function randomzap(x) =
let function f(y)=if random() then y else x
in f
end
randomzap の型チェックをする場合, let 式に対して, transexp (これは, の宣言に対して型チェック) を再帰的に呼び出す 必要がある.
- この位置では における の型は である.しかし generalize できない.
- は,勝手な型を引数として持つことはできない. と同じ型の 引数でなければならない.
- この位置では は (すでに) の型の記述として,
現在の環境 に出現する. 従って generalize のアルゴリズムは,以下のようになる.
に出現するメタ変数を
とする.
しかし, に出現しない場合,
( を検索する場合,メタ変数は を検索する
ことにより解釈しなければならない)
for to
let
return Poly
- すべての関数は Poly 型で与えられる.単相関数も Poly となる.
- generalization の反対は instantiation である. 多相変数が使われた場合,束縛された型変数をメタ変数に置換する.
( Poly
)=
to
return
- 多相関数を使うところ各々で, instantiation を処理しなけれ ばならない.
- ある呼ぶ側では,束縛変数 はメタ変数 ( int に される) に置換される.
- 別の呼ぶ側では はメタ変数 ( string に される) に置換される.
- またある呼び側では,全ての の使用に対して,お互いに一致 していなければならない.例えば randomzap 関数は, 多相型 poly<a> a->(a->a) を持つ.以下のように使われる.
let var i0 := randomzap(0)
var s0 := randomzap("zero")
in i0(3)+size(s0("three"))
end
これは以下のどれかを返す.,,,.
- randomzap の最初の出現では ( はメタ変数) と instantiate する.
- しかし,すべての は されなければならない. randomzap(0) の型チェックの場合は を int に する.
- i0(3) の型チェックの場合 は, を int に する.しかし, は既に int に instantiate されているので,ここでは が 一貫して使われているか,がチェックされる.
- それから i0(3)+ の型チェックをする場合には, は再び int に unify される.
- 同様に randomzap の第 2 の出現では, と instantiate され, は,すべて string に される( size の引数として "zero", "three" である).
更新可能変数
: 再帰的データ型 : 型推論 : 陰に型付けされた多相言語
平成12年8月22日