例えば、t1 が T→U 型をもち、t2 が S 型を持つとして、関数適用 t1 t2 に出会ったとき、「SはTの部分型か」を判断するために、部分型検査器アルゴリズムが呼び出される。
アルゴリズム的関係には、規則S-TRANS, S-REFLがない。
S-TRANSをなくすには、まず深さ・幅・並び替えの部分型付けを一つにまとめる規則を追加する必要がある。
{ li | i∈1..n } ⊆ { kj | j∈1..m } | kj = li ならば、Sj <: Ti | S-RCD |
{ kj : Sj | j∈1..m } <: { li : Ti | i∈1..n } |
> つまり..
レコードA{ kj : Sj }、レコードB{ li : Ti } について
- レコードAのラベル名の集合が、レコードBのラベル名の集合を含んでる
- それぞれの同じラベル名 kj, li について Sj <: Ti
ならば、レコードAはレコードBの部分型。
このS-RCDが、S-RCD-DEPTH, S-RCD-WIDTH, S-RCD-PERM(部分型付け規則の一部)を置き換えるものとして十分だということを、次の補題で証明してみよう。。
補題 16.1.1 S-RCD-DEPTH + S-RCD-WIDTH + S-RCD-PERM を含む部分型付け規則で S <: T を導出できる
⇄ S-RCD で S <: T を導出できる
各iに対して Si <: Ti | S-RCD-DEPTH |
{ li : Si | i∈1..n } <: { li : Ti | i∈1..n } |
| S-RCD-WIDTH |
{ li : Ti | i∈1..n+k } <: { li : Ti | i∈1..n } |
{ kj : Sj | j∈1..n } は { li : Ti | i∈1..n } の並び替えである | S-RCD-PERM |
{ kj : Sj | j∈1..n } <: { li : Ti | i∈1..n } |
⇅
{ li | i∈1..n } ⊆ { kj | j∈1..m } | kj = li ならば、Sj <: Ti | S-RCD |
{ kj : Sj | j∈1..m } <: { li : Ti | i∈1..n } |
証明)
導出に関する帰納法により、示す。
(→) S <: T を導出する最後の規則で場合わけをする
- S-RCD-DEPTHの場合
S-RCD において、{ li } ≡ { kj } であるようなケース。{ li } ≡ { kj } より、前提部 { li } ⊆ { kj } を導くことができる。 - S-RCD-WIDTHの場合
自明 - S-RCD-PERMの場合
{ kj : Sj } が { li : Ti } の並び替えであるなら、前提部 { li } ⊆ { kj } を導くことができる。
(←) S <: T を導出する最後の規則が S-RCDであるとして、
- 【{ li | i∈1..n } ⊆ { kj | j∈1..m } 】の部分
S-RCD-WIDTHに対応 - 【kj = li ならば、Sj <: Ti】の部分
ラベルの対応づけを行ってから型の対応関係を求めているので、S-RCD-PERM と S-RCD-DEPTH に対応
の性質と、帰納法の仮定で示せれる。
この証明によって、S-RCDが、S-RCD-DEPTH, S-RCD-WIDTH, S-RCD-PERM を置き換えるものとして十分だということが示せた。
結果的に得られる型システムを、以下(
図16-1) のようにまとめることができる。
図16-1: レコードのある部分型関係
| S <: U | U <: T | S-TRANS | S <: T |
|
| T1 <: S1 | S2 <: T2 | S-ARROW | S1 → S2 <: T1 → T2 |
|
{ li | i∈1..n } ⊆ { kj | j∈1..m } | kj = li ならば、Sj <: Ti | S-RCD |
{ kj : Sj | j∈1..m } <: { li : Ti | i∈1..n } |
では、次にS-TRANS, S-REFLが別のアルゴリズム的関係に置き換えることができることを示そう。
補題 16.1.2(1) すべての型Sについて、S <: S はS-REFLを使わずに導出できる
(2) もし S <: Tが導出可能ならば、 S <: T は S-TRANSを使わずに導出できる
証明)
(1) 型の大きさに関する帰納法で示す。
- S ≡ Top の場合
Top <: Top は、S-TOPにより示せる - S ≡ T1 → T2 の場合
T1 → T2 <: T1 → T2 は、S-ARROW により T1 <: T1, T2 <: T2 が成り立てばよいが、
これは帰納法の仮定により成立する。 - S ≡ { ki : Si ( i∈1..n ) } の場合
補題16.1.1(→)より、S-RCD-DEPTHはS-RCDで代用することができる。
これを適用すると、各iに対して Si <: Si が成り立てばよいことになるが、これは帰納法の仮定により成り立つ。
(2) 型の大きさに関する帰納法で示す。
S ≡ Top の場合
- T ≡ Top の場合
S-TOPにより成立。 - T ≡ T1 → T2 の場合
そもそも導出不可能。(Topの定義より) - T ≡ { li : Si } の場合
そもそも導出不可能。(Topの定義より)
S ≡ S1 → S2 の場合
- T ≡ Top の場合
S-TOPにより成立。 - T ≡ T1 → T2 の場合
S-ARROWにより、T1 <: S1, S2 <: T2 が成り立てばよい。あとは帰納法の仮定。 - T ≡ { li : Ti } の場合
そもそも導出不可能。※1
S ≡ { kj : Sj } の場合
- T ≡ Top の場合
S-TOPにより成立。 - T ≡ T1 → T2 の場合
そもそも導出不可能。※1 - T ≡ { li : Ti } の場合
S <: T は導出可能なので、補題15.3.2(2)'より、
{ li } ⊆ { kj } かつ li = kj では Sj <: Ti である。つまり、S-RCDを適用すればおk。
※1 補題15.3.2(2)を再証明することにより
よって、アルゴリズム的部分型付けは以下 (
図16-2) のようにまとめることができる。
※ 本章では、前章で扱った部分型付け判断式 S <: T の代わりに、|→ S <: T (「Sはアルゴリズム的にTの部分型になる」)という別の関係として表記する。
図16-2: アルゴリズム的部分型付け
|→ T1 <: S1 | |→ S2 <: T2 | SA-ARROW |
|→ S1 → S2 <: T1 → T2 |
{ li | i∈1..n } ⊆ { kj | j∈1..m } | kj = li ならば、|→ Sj <: Ti | SA-RCD |
|→ { kj : Sj | j∈1..m } <: { li : Ti | i∈1..n } |
演習 16.1.3もし、型Boolを追加したら、これらの性質はどう変化するだろうか。
証明)
型Boolを追加すると、型の構文規則が以下のようになる。
T | ::= | Top |
| | T → T |
| | { li : Ti ( i∈1..n ) } |
| | <b>Bool</b> |
ベースとなる型がひとつ増えるわけなので、以下のような規則を追加する必要がでてくる。
定義 16.1.4アルゴリズム的部分型関係は、
図16-2の規則に閉じた最小の関係である。
- 健全性 アルゴリズム的規則で導出できるすべての部分型付け判断式は、宣言的規則でも導出できる
- 完全性 宣言的規則で導出できる全ての部分型付け判断式がアルゴリズム的規則でも導出できる
命題 16.1.5[健全性と完全性] S <: T のとき、かつそのときのみ |→ S <: T
証明)
どちらも導出に関する帰納法で示す。
(→)
S <: T 導出木で、最後に適用した規則で場合分けする。
- S-REFL の場合
先の補題と導出の大きさに関する帰納法の仮定より。 - S-TRANS の場合
先の補題と導出の大きさに関する帰納法の仮定より。 - S-TOP の場合
SA-TOPを適用すればよい。 - S-ARROW の場合
導出の大きさに関する帰納法の仮定より、|→ T1 <: S1, |→ S2 <: T2 が成り立つので、これに SA-ARROWを適用すればよい。 - S-RCD の場合
略
(←)
略
これで、アルゴリズム的部分型関係を検査するアルゴリズムが完成した^^
このアルゴリズムを擬似コードとして書くと以下のようになる。
subtype(S, T) | = | if T = Top then true |
| | else if S = S1 → S2 and T = T1 → T2 |
| | then subtype(T1, S1) ^ subtype(S2, T2) |
| | else if S = { kj : Sj | j∈1..m } and T = { li : Ti | i∈1..n } |
| | then { li | i∈1..m } ⊆ { kj | j∈1..m } |
| | ^ すべてのiに対して、j∈1...mが存在し、kj = li かつ subtype(Sj, Ti) |
| | else false |
最後に、この関係が
全域的、つまり、この再帰関数subtypeが任意の入力に対して有限時間内に結果を返すことを検証する必要がある。
命題 16.1.6[停止性] もし |→ S <: T が導出可能ならば、subtype(S, T)は true を返す。そうでないなら、false を返す。
証明)
再帰時の引数の大きさの和は、入力S, Tの大きさの和より真に小さいので、ちゃんと止まる。
【「はじめっから、アルゴリズム的定義でやれば良いのでは?」と思った人へ】
まあその通りなのだが、型付け関係の正当性を示すためには、「部分型付けが反射的・推移的である」ことを知る必要があるので、どっちの定義を先に持ってきても作業量はさほど変わらないよ。