「ソフトウェア基礎科学」補助資料
∗
http://www.kb.ecei.tohoku.ac.jp/˜koba/class/soft-kiso/小林 直樹
1
型システムの初歩
型なしλ
計算では,いろいろなデータ(ブール値,整数,組など)や制御(if文,再帰)がλ項 として表現できるが,一方で,その自由度ゆえに,プログラミング言語としてみた場合には不適切 な面も多い.例えば,一つのλ項がいろいろな意味に解釈できてしまう(例えばλx.λy.y
はブール 値のfalse
としても解釈できるし,整数の0
としても解釈できる).そこで,型つきλ
計算(typedλ-calculus
)では各項にその項がどのような値かを表す「型」を与え,各項(データ)が意図した型 で扱われるように「型システム」によって許される項の集合を制限する.以下では,まず型付きλ
計算の最も単純なものである,単純型付きλ
計算について解説する.1.1
単純型つきλ
計算1.1.1
構文 型とλ
→,×項のsyntax
を次のように定義する.τ (types)
::= b
| τ
1→ τ
2| τ
1× τ
2M (terms)
::= c
τ| x | M
1M
2| λx : τ.M | (M
1, M
2)
| fst(M) | snd(M)
メタ変数b
は、基底型とよばれる型(整数型int
、ブール型bool
など)の集合を動くものとする.型
τ
1× τ
2は,型τ
1の値と型τ
2の値とのペアの型を表す.例えば,(1, true)
は,型int
× bool
を持 つ. 項の構成子には,型なしλ
計算に比べて,定数項c
τ など,いくつか追加してある1.メタ変数c
τ は,τ
型の定数を表す.ただし,ここでは定数の型τ
は,b
,b
1→ b
2, b
1×b
2→ b
のいずれかのみ であるとし,型b
1→ b
2の定数c
b1→b2には,型b
1の定数の集合から型b
2の定数の集合への(全) 関数[[c
b1→b2]]
が存在するものとする.同様に,型b
1× b
2→ b
の定数c
b1×b2→bには型b
1の定数と 型b
2の定数のペアの集合から型b
の定数の集合への関数[[c
b1×b2→b]]
が存在するものとする.(型b
の定数c
bには,構文と意味を同一視して,c
b自身を集合b
の要素とみなすことにする) ∗講義内容とは必ずしも一致しないので,講義をきちんと聞くこと 1これらは必須ではないが,型なしλ計算と異なり,整数やブール値などをλ項として表現してしまうと,違う種類の データに同じ型がつけられてしまうので,それらを定数として扱う.例えばブール値のfalseと自然数の0は型なしλ計 算では同じλx.λy.xとなってしまう.c
τ において,型τ
が明らかな場合には,省略して単にc
と書く.例えば整数1
int は単に1
と書く. λ抽象には,λx : τ.M
のように,変数x
に渡されるべき値の「型」を注釈として書くことにす る(これは,C
言語やJava
言語などの変数宣言に対応する).後で述べるように,実は単純型付 きλ計算の場合にはこれらの型は自動的に推論可能であるので,プログラマは省略することができ る.(実際,ML
という関数型言語では,変数の型宣言をしなくてもよい) 項(M
1, M
2)
は,M
1(の値)とM
2(の値)のペアを表す.fst (M )
はペアM
の第一要素を,snd (M )
はペアM
の第二要素を取出す.1.1.2
操作的意味 ここでは,call-by-value
戦略にしたがった操作的意味を下に与える.代りにcall-by-name
戦略 を用いても,後の型システムの議論にはほとんど影響はない.V (value) ::= c
τ| λx.M | (V
1, V
2)
(λx.M )V
−→
cbv[V /x]M
(R-Beta)
c
b1→bc
b1 1−→
cbv[[c
b1→b]] (c
b11)
(R-Const1)
c
b1×b2→b(c
b1 1, c
b22)
−→
cbv[[c
b1×b2→b]] (c
b11, c
b22)
(R-Const2)
M
−→
cbvM
M N
−→
cbvM
N
(R-App1)
N
−→
cbvN
V N
−→
cbvV N
(R-App2)
M
1−→
cbvM
1(M
1, M
2)
−→
cbv(M
1, M
2)
(R-Pair1)
M
2−→
cbvM
2(V, M
2)
−→
cbv(V, M
2)
(R-Pari2)
M
−→
cbvM
fst (M )
−→
cbvfst (M
)
(R-Fst1)
fst (V
1, V
2)
−→
cbvV
1(R-Fst2)
M
−→
cbvM
snd (M )
−→
cbvsnd (M
)
(R-Snd1)
snd (V
1, V
2)
−→
cbvV
2(R-Snd2)
1.1.3
型システムλ
→,×においては、上で定義したsyntax
によって構成されるすべてのterm
に興味があるわけで はない.すなわち、対象とするのは、上のsyntax
によって構成され、かつ「型に関する整合性があ る」項のみである.例えば、(λx : int .x)true
という項は、引数として整数を要求している関数に ブール値を適用しようとしているので型に関して整合性がとれていない 「型に関する整合性がある」ということをformal
に表すために、3項関係“Γ
M : τ”
を考 える.「型環境」Γ
は、変数の有限集合から型への写像である.“Γ
M : τ”
は、「型環境Γ
の もとで、M
は型τ
をもつ」と読む.その意図は,「各変数に型環境Γ
に従った型の値が束縛され ているもとでM
を評価すると,(存在するならば)評価結果は型τ
の値である」という意味であ る.この関係は以下のような(型つけ規則と呼ばれる)規則によってinductive
に定義される.規 則T-Var
やT-Abs
のΓ, x : τ
は,型環境Γ
のx
に対応する値をτ
に置き換えて(または追加して) 得られる型環境を表す.Γ
c
τ: τ
(T-Const)
Γ, x : τ
x : τ
(T-Var)
Γ
M
1: τ
1→ τ
2Γ
M
2: τ
1Γ
M
1M
2: τ
2(T-App)
Γ, x : τ
1M : τ
2Γ
λx : τ
1.M : τ
1→ τ
2(T-Abs)
Γ
M
1: τ
1Γ
M
2: τ
2Γ
(M
1, M
2) : τ
1× τ
2(T-Pair)
Γ
M : τ
1× τ
2Γ
fst(M) : τ
1(T-Fst)
Γ
M : τ
1× τ
2Γ
snd(M) : τ
2(T-Snd)
Γ
M : τ
が上のルールによって導ける時、「M
は型環境Γ
のもとで型づけ可能(well-typed)
で ある」という.Remark 1.1:
上の導出において,束縛変数のつけかえ(α
変換)によって得られる項は同一のも のとみなし,束縛変数の名前は必要に応じて名前のつけかえを行うものとする.例えばの型λx:int .λx:
bool .x
は以下のように導出する.x : int , y : bool
y : bool
x : int
λy : bool.y(= λx : bool.x) : bool → bool
∅ λx : int.λx : bool.x : int → bool → bool
Exercise
次の各term
について、Γ
M : τ
を満たす組Γ, τ
は存在するか?もし存在するなら ばその組を一つあげよ.1. λx : int .yx
2. xx
3. λz : (int
→ int → int).zxy
4. (xy)(xz)
5. (yx)(zx)
任意の型環境Γ
と項M
について、Γ
M : τ
を満たすτ
はunique
であることが次の定理から わかる(これは一般の型システムでは必ずしも成り立たない).Theorem 1.2: Γ
M : τ
1かつΓ
M : τ
2ならばτ
1= τ
2.
Exercise
上の定理を証明せよ.1.1.4
型システムの健全性(Type Soundness)
λ
項をプログラムとみた場合,本来関数であるべきところに整数がきたり(例:1(2)),定数関
数に要求されているのとは違う引数が与えられたり(例:+
int×int→int(true, 1)),
fst
やsnd
にペ アでないものが与えられたり(例:fst (1)
)しては困る.通常の型システムはそのような「実行時 型エラー」が起こらないように設計されている2.型システムで型づけされた閉じた項(自由変数を 含まない項,プログラム)は実行時型エラーを起こさないことが保証されているとき,その型シス テムは(操作的意味に対して)健全であると言う.1.1.3節で定義した型システムも健全である.そのことを以下で確認しよう.まず,「実行時型エ
ラー」は,1.1.2節の操作的意味では,「値になっていないのに,適用すべき規則がない状態」とし
てとらえることができる.実際,fst (1)
のような項については,適用できる規則がないことに注意 してほしい. 型システムの健全性は,以下の2つの性質によって保証される.一番目の性質(定理1.3)は,プ
ログラムM
が型づけ可能であり,値でないならば,まだ簡約が行えることを表す.二番目の性質 (定理1.4, subject reduction
とも呼ばれる)は,型づけが簡約によって保存されることを表す.こ れらの性質から,プログラムM
が型づけ可能であれば,M
が値に簡約されるまでは簡約をつづけ て行うことができる(系1.10),つまり実行時型エラーは決して起こらないことが言える.
Theorem 1.3 [Progress]:
もし∅ M : τ
かつM
が値でないならば,あるM
が存在してM
−→
cbvM
が成り立つ.Proof:
M
の構造に関する帰納法により示す.• M = c
τのとき.M
は値であるので明らか. 2C言語のようにそうでないものも存在する• M = x
のとき.∅ M : τ
は成り立たないので明らか.• M = M
1M
2のとき.∅ M : τ
であるとすると,あるτ
1が存在して∅ M
1: τ
1→ τ
かつ∅ M
2: τ
1.M
1が値でないならば,帰納法の仮定より,M
1−→
cbvM
1 を満たすM
1 が存 在するので,M
= M
1M
2とおけば,M
−→
cbvM
.M
1が値である場合,型づけ規則よ り,M
1= c
τ1→τ またはM
1= λx.M
1.M
2が値であるかどうかにより場合分けを行う.– M
2が値でない場合: 帰納法の仮定より,M
2−→
cbvM
2 を満たすM
2 が存在するので,M
= M
1M
2 とお けばM
−→
cbvM
.– M
2が値である場合:M
1= λx.M
1 のときは,M
= [M
2/x]M
1 とおけば,規則R-Beta
よりM
−→
cbvM
.M
1= c
τ1→τ のとき.定数の型に関する仮定から,τ
1→ τ = b
1× b
2→ b
またはτ
1→
τ = b
1→ b
.前者の場合,∅ M
2: b
1× b
2かつM
2が値なので,M
2= (c
b1 1, c
b22).
よって,M
= [[c
b1×b2→b]] (c
b1 1, c
b22)
とおけば,規則R-Const2
より,M
−→
cbvM
. 後者の場合,∅ M
2: b
1かつM
2が値なので,M
2= c
b11.よって,M
= [[c
b1→b]]
(c
b11)
とおけば規則R-Const1
より,M
−→
cbvM
.• M = λx : τ.M
1のとき.M
は値なので明らか.• M = (M
1, M
2)
のとき.∅ M : τ
かつM
が値でない(つまりM
1またはM
2のいずれかは 値でない)と仮定する.型づけ規則より,τ = τ
1×τ
2,∅ M
1: τ
1,かつ∅ M
2: τ
2.M
1 が値でないとき,帰納法の仮定より,M
1−→
cbvM
1 を満たすM
1 が存在し,M
= (M
1, M
2)
とおけばM
−→
cbvM
が成り立つ.M
1が値であり,M
2が値でないときは帰納法の仮定 より,M
2−→
cbvM
2 を満たすM
2 が存在し,M
= (M
1, M
2)
とおけば規則R-Pair2
よりM
−→
cbvM
が成り立つ.• M = fst(M
1)
のとき.型づけ規則より,∅ M : τ
ならば,∅ M
1: τ
× τ
2.M
1が値 でなければ,帰納法の仮定よりM
1−→
cbvM
1 を満たすM
1 が存在し,M
= fst (M
1)
とお けば,M
−→
cbvM
が成り立つ.M
1が値ならば,型づけ規則より,M
1= (V
1, V
2).よっ
て,M
= V
1とおけば,規則R-Fst2
よりM
−→
cbvM
.• M = snd(M
1)
のとき.M = fst (M
1)
の場合と同様.Theorem 1.4 [
型保存定理(Type Preservation)]:
もしΓ
M : τ
かつM
−→
cbvM
なら ば,Γ
M
: τ
が成り立つ.上の型保存定理の証明の前に,補題を用意する.下で
Γ
⊆ Γ
は型環境Γ, Γ
を集合としてみたときの包含関係,つまり
∀x.∀τ.(Γ(x) = τ ⇒ Γ
(x) = τ )
を表す.Lemma 1.5 [weakening]: Γ
M : τ
かつΓ
⊆ Γ
ならば,Γ
M : τ
.Exercise 1.6:
上の補題を証明せよ.Lemma 1.7 [substitution lemma]: Γ
M
1: τ
1かつΓ, x : τ
1M
2: τ
2ならば,Γ
[M
1/x]M
2: τ
2が成り立つ.Proof:
M
2の構造に関する帰納法.代表的な場合についてのみ示す.• M
2= x
のとき.[M
1/x]M
2= M
1より明らか.• M
2= y(
= x)
のとき.[M
1/x]M
2= y.
Γ, x : τ
1M
2: τ
2ならばΓ(y) = τ
2なので,Γ
[M
1/x]M
2: τ
2.• M
2= λy : τ
21.M
2 のとき.Γ, x : τ
1M
2: τ
2より,Γ, x : τ
1, y : τ
21M
2: τ
22か つτ
2= τ
21→ τ
22.Lemma 1.5より,
Γ, y : τ
21M
1: τ
1なので,帰納法の仮定より,Γ, y : τ
21[M
1/x]M
2: τ
22が成り立つ.T-Abs
より,Γ
λy : τ
21.[M
1/x]M
2: τ
21→ τ
22, つまりΓ
[M
1/x]M
2: τ
2.Exercise 1.8:
上の証明で,他の場合について示して証明を完成させよ.Proof of Theorem 1.4:
M
−→
cbvM
の導出に関する帰納法.最後の規則により場合わけを 行う.以下は代表的な場合に付いてのみ示す.• R-Beta
の場合.M = (λx.M
1)M
2かつM
= [M
2/x]M
1.Γ
M : τ
より,Γ, x : τ
1M
1: τ
かつΓ
M
2: τ
1.Lemma 1.7より,
Γ
M
: τ
が成り立つ.• R-Const1
の場合.M = c
b1→bc
b1 1 かつM
= [[c
b1→b]] (c
1b1) = c
b2かつτ = b
.T-Const
よ り,Γ
M
: τ
.• R-App1
の場合.M = M
1M
2かつM
= M
1M
2かつM
1−→
cbvM
1.Γ
M : τ
よ り,Γ
M
1: τ
1→ τ
かつΓ
M
2: τ
1.帰納法の仮定より,Γ
M
1: τ
1→ τ
.よっ て,T-App
より,Γ
M
: τ
.Exercise 1.9:
上の証明で,他の場合について示して証明を完成させよ.Corollary 1.10 [Type Soundness]:
もし∅ M : τ
かつM
−→
∗cbvM
−→
cbvならば,M
は値である.
1.1.5
Strong Normalization
λ
→,×においては、型づけ可能な項は、どんな順序でβ-reduction
(call-by-value 戦略−→
cbvに限る必要はない)を施しても必ず有限ステップで
normal form
に簡約できることが保証されている.
Theorem 1.11 [strong normalization]: Γ
M : τ
ならば、無限のβ
簡約列M
−→ M
β 1−→
βM
2−→ · · ·
β は存在しない.証明は
[2]
を参照せよ.注 上の
strong normalization
に関する定理は、非常によい性質である反面、λ
→,×の表現力が弱いことを意味する(total functionしか表現できない).実際のプログラミング言語として用いると
きには,
strong normalization
の性質はあきらめ,fixed point operator fix
(τ1→τ2)→(τ1→τ2)を定数として導入して再帰を表現できるようにする.
1.1.6
型推論とPrincipal Typing
λ
→,×をプログラミング言語としてとらえた場合、λx : τ.M
のように、各関数の引数について型を宣言するのは面倒である.そこで、型宣言を省略した以下のような言語を考え、
e (terms)
::= c
τ| x | e
1e
2| λx.e | (e
1, e
2)
| fst(e) | snd(e)
e
から、Γ
M : τ
を満たすΓ, M, τ
(M
はe
に型宣言を付加して作られる項)を自動的にみつ けることは可能だろうか?e
の形によっては、そのようなΓ, M, τ
の組は無限に存在する.例えばe = x
とすると、任意のτ
についてx : τ
M : τ
が成り立つ.同様に、e = λx.x
とすると任 意のτ
について∅ λx : τ.x : τ → τ
が成り立つ.このように無限の数の組を一つ一つ列挙する のはreasonable
ではない.ところが幸い、型のsyntax
を若干変更すれば、Γ
M : τ
をみたすΓ, M, τ
の中で、「最も一般的な」ものが一つ存在することがわかる. 型のsyntax
に、次のように型変数を導入する.τ (types)
::= α (type variables)
| b | τ
1→ τ
2| τ
1× τ
2λ
→,×項M
からすべての型宣言をとりさってできる(型なし)項をErase(M )
と書くことにする.与えられた
e
に対して、上で述べた「最も一般的な」Γ, M, τ
とは次のように定義できる.Definition 1.12 [principal typing]: (Γ, M, τ )
は以下の条件を満たす時、(型なし)項e
のprin-cipal typing
であるという.1. Erase(M ) = e
2. Γ
M : τ
3. Γ
M
: τ
, Erase(M
) = e
を満たす任意のΓ
, M
, τ
について、次の条件を満たす型変数(a) θΓ
⊆ Γ
(b) θM = M
(c) θτ = τ
すなわち、Γ, M, τ
は、(1)正しい型つけであり、(2)すべての正しい型つけは型変数への代 入および余分な型環境の付加によってえられ, かつ(3)逆に型変数への代入および余分な型環境 の付加によってえられる組はすべて正しい型つけである(これは上の条件には入っていないが型つ け規則から直ちにいえる)とき、principal typing
であると呼ばれる.λ
→,×についてはprincipal typing
は単一化(unification)アルゴリズムmgu
3を用いて以下のよ うに容易に求めることができる.P T (c
τ)
= (
∅, c
τ, τ )
P T (x)
= (x : α, x, α) where α is fresh
P T (e
1e
2)
= let
(Γ
1, M
1, τ
1) = P T (e
1)
(Γ
2, M
2, τ
2) = P T (e
2)
θ = mgu(
{(τ
1, τ
2→ α)} ∪ {(Γ
1(x), Γ
2(x))
| x ∈ dom(Γ
1)
∩ dom(Γ
2)
})
where α is fresh
in ((θΓ
1)
∪ (θΓ
2), θ(M
1M
2), θα)
P T (λx.e)
= let
(Γ, M, τ ) = P T (e)
in if x
∈ dom(Γ)
then (Γ
\x, λx : Γ(x).M, Γ(x) → τ)
else (Γ, λx : α.M, α
→ τ)
where α is fresh
P T ((e
1, e
2))
= let
(Γ
1, M
1, τ
1) = P T (e
1)
(Γ
2, M
2, τ
2) = P T (e
2)
θ =
{(Γ
1(x), Γ
2(x))
| x ∈ dom(Γ
1)
∩ dom(Γ
2)
})
in ((θΓ
1)
∪ (θΓ
2), θ((M
1, M
2)), θ(τ
1× τ
2))
P T (fst (e))
= let
(Γ, M, τ ) = P T (e)
θ = mgu(
{(τ, α × β)}
where α,β are fresh
in (θΓ, θ(fst (M )), θα)
P T (snd (e))
= let
(Γ, M, τ ) = P T (e)
θ = mgu(
{(τ, α × β)}
where α,β are fresh
in (θΓ, θ(snd (M )), θβ)
3型のペアの有限集合{(τ11, τ12), . . . , (τn1, τn2)}を受け取り,等式τ11 = τ12, . . . , τn1 = τn2の最汎単一化子(most
Exercise
上のアルゴリズムに従って、principal typing
を求めるプログラムを作成せよ.(ML またはProlog
を使うと楽である)1.2
Polymorphism
λ
→,×においては、各変数には特定の型の値しか束縛することができない.これは、プログラムの 再利用性の点において非常に都合がわるい.例えば、恒等関数はどんな型についてもλx.x
と書け るはずなのに、それぞれの型ごとにλx : τ.x
を用意しなければならない.このような欠点を克服 するため、これまでに多くの型システムの改良が提案・研究されてきている(一般に、上のように 各部分式が単一の型の値としてしか用いることができないような型システムを単相(monomorphic)
型システム、以下で述べる改良のように複数の型の値として用いることができるようなものを多相(polymorphic)
型システムと呼ぶ).ここではそれらのうちの代表的なものとしてML
で用いられ ているparametric polymorphism
について紹介する.1.2.1
λ
→,∀ 上で例に考えた恒等関数λx : τ.x
がどのようにしたら再利用できるかを考えよう.(型を明示的 に指定しないで単にλx.x
と書き、型推論によって文脈に応じてλx : τ.x
と型を再構成すればよい と思うかもしれないがこれはうまくいかない.(λx.xx)(λx.x)
が型づけできないことからわかるよ うに、λ
→,×の枠組の中で考えているかぎり、一つの式を複数の型の値として用いることはできな い.) ここで、各型用の恒等関数はλx : τ.x
中のτ
の部分だけが異なることに着目しよう.そこで、型 変数に関するλ
抽象を許すことにすれば、λx : τ.x
は、(Λα : U
1.λx : α.x)τ
のように表すことがで きる.したがって、Id = Λα : U
1.λx : α.x
とおけば、各Id
τ= λx : τ.x
は,Id
の型τ
への適用Id[τ ]
によって得られ、Id
の部分が共有でき ることになる.同様にして、2つの関数を合成する関数compose
は、compose = Λα : U
1.Λβ : U
1.Λγ : U
1.λf : β
→ γ.λg : α → β.λx : α.f(g(x))
と書ける.上でU
1と書いたのは「型の型」のようなものであり、τ : U
1によって「τ
は型である」 ことを表す.意味的には、U
1は次によって定義される型の集合と考えればよい.τ ::= α
| b | τ
1→ τ
2| τ
1× τ
2Id
やcompose
の「型」はどのように表せばよいだろうか?それらはU
1の要素によって表すことは できず、新たに型に関する構成子を導入する必要がある.Id
はあらゆる型τ
についてτ
→ τ
とい う型の値を返すので、∀α : U
1.(α
→ α)
のように書く. 同様にして、compose
の型は∀α : U
1.
∀β : U
1.
∀γ : U
1.((β
→ γ) → (α → β) → α → γ)
と表すことができる.U
1に∀α
1: U
1.
· · · ∀α
n: U
1.τ
の形の型を追加した型の集合をU
2と書くこと にし、U
2の型を表すメタ変数としてσ
を用いる.Remark 1.13: U
2は、以下によって定義される型の集合U
(後述のimpredicative polymorphism
を参照.)とは異なることに注意せよ.τ ::= α
| b | τ
1→ τ
2| τ
1× τ
2| ∀α : U.τ
例えば,(
∀α.α) → (∀α.α)
はU
2の型ではない. 以上にしたがって項のsyntax,
型つけ規則を定義すると以下のようになる.(:U1は省略する.ま た,ペアの構成子は本質的でないので省略する)Definition 1.14 [λ
→,∀-term]:
M ::= c
σ| x | M
1M
2| λx : τ.M | Λα.M | M[τ]
Γ
c
σ: σ
(TPoly-Const)
Γ, x : σ
x : σ
(TPoly-Var)
Γ
M
1: τ
1→ τ
2Γ
M
2: τ
1Γ
M
1M
2: τ
2(TPoly-App)
Γ, x : τ
1M : τ
2Γ
λx : τ
1.M : τ
1→ τ
2(TPoly-Abs)
Γ
M : σ
α not free in Γ
Γ
Λα.M : ∀α.σ
(TPoly-∀-Intro)
Γ
M : ∀α.σ
Γ
M[τ] : [τ/α]σ
(TPoly-∀-Elim)
1.2.2
λ
→,∀,let さて、λ
→,∀自身は、多相関数を用いる上で不十分である.例えば、untyped λ-calculus
の(λx.xx)(λx.x)
に相当するterm
は、一見(λx :
∀α.(α → α).(x[τ → τ])(x[τ]))(Λα.λx : α.x))
のように表せばいいように見えるが、λx :
∀α.(α → α).(x[τ → τ])(x[τ])
の部分は、∀α.(α → α)
の値をとってτ
→ τ
の型の値を返す関数となり、それを表す型が存在しない((∀α.(α → α)) →
(τ
→ τ)
はもはやU
1の型でもU
2の型でもないことに注意).これに対する解決策としては以下の 2通りが考えられる.•
型の集合を拡張し、σ ::= α
| b | σ
1→ σ
2| ∀α.σ
のように定義する.
∀α.σ
のように型全体に関して言及した型もまた型として扱われるので、 型の意味はもはや単純な集合論ではとらえることができない.このような多相型システムはimpredicative polymorphsim
とよばれ、Girard
とReynolds
によって独自に提案され、そ の後盛んに研究されている.•
新しい項のconstruct
を導入し、部分的に多相性を導入する.これがプログラミング言語ML[1]
で用いられている方法である. ここでは後者の方法を解説する.まず項のsyntax
を次のようにlet
式を導入して拡張する.M ::= x
| M
1M
2| λx : τ.M | Λα.M | M[τ] | let x : σ = M
1in M
2end
そして、次のlet
式に対する型つけ規則を追加する.Γ
M
1: σ
Γ, x : σ
M
2: τ
Γ
let x : σ = M
1in M
2end : τ
(TPoly-Let)
ここで、
x
がM
2の中でU
2の型σ
の値として用いることができることに注意.したがって、let
でbind
された変数はそのbody
中でpolymorphic
に用いることができる.これによって上記の例は、let x :
∀α.(α → α) = Λα.λx : α.x in (x[τ → τ])(x[τ]) end
と記述できる.一方、λ
抽象によってbind
された変数は、あいかわらずmonomorphic
にしか用い ることができない.1.2.3
λ
→,∀,letに関する型推論λ
→の時と同じく、型推論の問題は、「型に関する記述を取り除いた項e
から、Γ
M : σ, Erase(M) =
e
を満たす3つ組(Γ, M, σ)
を求める」こととして定義できる.「型なし項」のsyntax
および型を 取り除く変換Erase
は次のように定義できる.e ::= x
| e
1e
2| λx.e | let x = e
1in e
2end
Erase(x)
= x
Erase(M
1M
2)
= Erase(M
1)Erase(M
2)
Erase(λx : τ.M )
= λx.Erase(M )
Erase(Λα.M )
= Erase(M )
Erase(M [τ ])
= Erase(M )
Erase(let x : σ = M
1in M
2end)
= let x = Erase(M
1) in Erase(M
2) end
型なし項の
syntax
はML
の核部分の言語であり、したがって、ML
における型推論の問題は、ま さにλ
→,∀,letに対する型推論の問題としてとらえることができる. さて、λ
→,∀,letに対する型推論はλ
→,×に対するそれほど単純ではない.それをみるために、型 つけ規則の中の項M
をErase(M )
で置き換えた規則を考えよう.Γ
e : σ
α not free in Γ
Γ
e : ∀α.σ
(T-ML-∀-Intro)
Γ
e : ∀α.σ
Γ
e : [τ/α]σ
(T-ML-∀-Elim)
· · ·
上に示した一部の規則からわかるように、λ
→,×の場合と異なり、もはや一つの型なし項の形に対 して適用できる型つけ規則が複数存在する.したがって、もとの項M
に対する型つけがどの規則か ら導かれたのかをしることができない.ところが、以下に示すように、T-ML-∀-Intro, T-ML-∀-Elim
が 限られた場所でしか適用できないことを利用して、上の規則の集合と等価であり、かつそれぞれの 項の形に対して適用できる規則が一つしかないような規則に変形できる. まず、T-ML-∀-Elim
の出現場所を考えてみよう.すると、仮定部分がU
2の型なので、T-ML-∀-Elim
が 適用される前のルールは、結論部にU
2の型をもつものでなければならない.したがって、TPoly-Var
あるいは
T-ML-∀-Elim, T-ML-∀-Intro
のいずれかである.ところが、直前がT-ML-∀-Intro
の 場合には導出木は· · ·
Γ
e : σ
Γ
e : ∀α.σ
Γ
e : [τ/α]σ
の形になっているので、部分導出木· · ·
Γ
e : σ
中のα
をτ
で置き換えてできる導出木· · ·
Γ
e : [τ/α]σ
で置き換えることができる.したがって、「T-ML-∀-Elim
は、TPoly-Var
のあとに連続して適 用されるのみである」と制限することができる.同様にして,「T-ML-∀-Intro
は,TPoly-Let
の 直前に左側の条件部を導出するのに用いられるのみ」と制限することができる.以上から、λ
→,∀,let の(型なし項に対する)型つけ規則は、以下のものと(Γe : τ
という形のtype judgement
につ いては)等価であることがわかる.Γ, x :
∀α.τ
x[τ] : [τ/α]τ
(T-ML-Var)
Γ
M
1: τ
1→ τ
2Γ
M
2: τ
1Γ
M
1M
2: τ
2(T-ML-App)
Γ, x : τ
1M : τ
2Γ
λx : τ
1.M : τ
1→ τ
2(T-ML-Abs)
Γ
M
1: τ
1Γ, x :
∀α.τ
1M
2: τ
2{α}
はτ
1に出現するがΓ
には出現しない型変数の集合実は
λ
→,∀,letそのものに対してはλ
→,×で考えたようなprincipal typing
は存在しない.ところ が、型推論の問題を適当に限定することで、principal typing
が存在するようにできる.すなわち、e
から、(Γ, M, σ)
を求める上で、Γ, σ
を「U
1の型しか含まない」と限定すると、任意のe
に対し て最も一般的な(Γ, M, σ)
が常に存在する.閉じた項については、型環境が空でよいので、そのよ うな限定した仮定のもとでの最も一般的なM, τ
は、もともとのλ
→,∀,letにおけるそれに一致する. 限定した仮定のもとでのprincipal typing
およびそれを求めるアルゴリズムは以下のようになる. アルゴリズムの引数A
には,途中で求まった,let
式で束縛された変数のU
2の型が格納される.e
の