「構造的部分型と有界量化に関する型推論」からリンクされているsubtyping.pdfにはいくつかの誤謬・誤植や非自明な点があると感じました。
ページ10の θΓ := {x ↦ θτ | (x ↦ τ) ∈ Γ}
でτ
が用いられていますがσ
が適切ではないでしょうか。
説明なくθ ∘ θ'
のような合成がされています。
次のように定義されるでしょう。
(θ ∘ θ')α :=
θτ (α ↦ τ) ∈ θ' である場合
τ (α ↦ τ) ∈ θ であり、α ∉ dom θ' である場合
θΓ
を定義するために必要です。
θ(∀α :: κ. σ) :≡ ∀α :: θκ. θσ α ∉ FTV(θ) かつ α ∉ dom θの場合
適宜α変換を行うことによって全域的な操作とすることができます。
FTV(∀α :: κ.σ) := FTV(σ) ∪ FTV(κ) ∖ {α}
実際の実装では順序付き組を用いて表現するので、図4に書いてある通りに実装するとUnifyAux
関数の引数のパターンマッチに失敗してしまうことがあります。
ページ6の置換の定義では変数捕縛が起きてしまうと思います。
(実装方法によっては、かつInfer(∅, ∅, e)
しか実行しない場合は、変数捕縛に注意を払わずに実装しても問題が起きないため厄介です。)
図2のInfer
関数の「項が関数適用」であるケースでβ := FreshTypeVar()
とした後に種環境をβ ↦ U
で拡張しないと、種環境に存在しない型変数が発生してしまいます。
図4のUnifyAux
関数において、α1 ≟ α2
の形をした制約を扱う際、
K' := ([α2/α1]K)[α1 ↦ ...]
となっていますが
K' := ([α2/α1]K)[α2 ↦ ...]
が正しいと思われます。
10ページ目のClose
関数に誤りがあります。
(FTV(K) ∪ FTV(τ)) ∖ FTV(Γ)
となっていますが、
EFTV(K, τ) ∖ EFTV(K, Γ)
が適切かと思われます。
EFTV
は(Ohori 1995)で定義されていて、essentially free type variables
を表すものであり、次の二つの条件を満たす最小の集合です(表記はsubtyping.pdfに合わせています)。
1. FTV(σ) ⊆ EFTV(K, σ).
2. if α ∈ EFTV(K, σ) then FTV(K(α)) ⊆ EFTV(K, σ).
これはΓ
にも自然に(FTV
と同じように)拡張されます。
現在のClose
関数の定義のままだと、例えば
e ≡ (λx. let y = (λz. f (x#r) z) in x#r)
Γ ≡ Γ'[f ↦ ∀α :: U. α → α → α]
であるとき、Infer(K, Γ, e)
で型を推論することができない(はず)です。
また8ページ目の図1のΛα : κ. M
に対する型つけ規則において、α ∉ FTV(Γ)
はα ∉ EFTV(K[α ↦ κ], Γ)
に置き換えられるべきです。(Ohori 1995)ではFTV
が用いられています(Fig. 5)が、それはα ∉ dom K
であることを前提にしているからです。
図4のUnifyAux
関数は{R} ≟ {R}
(両方がレコード型)であるケースにも対応するほうが良いかもしれません。
閉じた項をInfer
関数に渡したときにそのような制約が発生することはないと思われますが、
型環境に{R} → τ
型の項がある場合(や、「明示的に型を指定する仕組み」(例えばλx:τ.M
のようなλ抽象)を追加した場合)に発生し得ます。
Atsushi Ohori. A Polymorphic Record Calculus and Its Compilation. ACM Transactions on Programming Languages, vol. 17, no. 6, 844–895, 1995.