免責事項
あなたが要求したように、これは非常に非公式です。
文法
依存型付けされた言語では、型レベルと値レベルでバインダーがあります。
Term = * | (∀ (Var : Term). Term) | (Term Term) | (λ Var. Term) | Var
まあ型付けされた用語が添付型の用語であり、我々は書きますt ∈ σか
σ
t
用語tにタイプがあることを示すためσ。
入力規則
単純にするために、λ v. t ∈ ∀ (v : σ). τ両方λでそれを要求し∀、同じ変数をバインドします(vこの場合)。
ルール:
t ∈ σ is well-formed if σ ∈ * and t is in normal form (0)
* ∈ * (1)
∀ (v : σ). τ ∈ * -: σ ∈ *, τ ∈ * (2)
λ v. t ∈ ∀ (v : σ). τ -: t ∈ τ (3)
f x ∈ SUBS(τ, v, x) -: f ∈ ∀ (v : σ). τ, x ∈ σ (4)
v ∈ σ -: v was introduced by ∀ (v : σ). τ (5)
したがって、*「すべての型の型」(1)、∀型(2)から型を形成し、ラムダ抽象はpi型(3)を持ち、vによって導入された場合∀ (v : σ). τ、v型σ(5)を持ちます。
「標準形式」とは、削減ルールを使用してできるだけ多くの削減を実行することを意味します。
「The」削減ルール
(λ v. b ∈ ∀ (v : σ). τ) (t ∈ σ) ~> SUBS(b, v, t) ∈ SUBS(τ, v, t)
where `SUBS` replaces all occurrences of `v`
by `t` in `τ` and `b`, avoiding name capture.
または二次元構文で
σ
t
意味t ∈ σ:
(∀ (v : σ). τ) σ SUBS(τ, v, t)
~>
(λ v . b) t SUBS(b, v, t)
用語が関連するforall量指定子の変数と同じタイプの場合にのみ、用語にラムダ抽象化を適用できます。次に、前の純粋なラムダ計算と同じ方法で、ラムダ抽象化とforall量指定子の両方を削減します。値レベルの部分を差し引いた後、(4)タイピング規則が得られます。
例
関数適用演算子は次のとおりです。
∀ (A : *) (B : A -> *) (f : ∀ (y : A). B y) (x : A). B x
λ A B f x . f x
(言及しない場合は省略∀ (x : σ). τしσ -> τますτx)
ftypeのB y提供に対して返されます。に適用します。これは正しいタイプで、afterの代わりに使用します。したがって、〜>yAfxAyx∀.f x ∈ SUBS(B y, y, x)f x ∈ B x。
関数適用演算子as appを省略して、それ自体に適用してみましょう。
∀ (A : *) (B : A -> *). ?
λ A B . app ? ? (app A B)
私?たちが提供する必要のある条件を設けます。まず、明示的に導入およびインスタンス化してA、およびB:
∀ (f : ∀ (y : A). B y) (x : A). B x
app A B
今、私たちは持っているものを統一する必要があります
∀ (f : ∀ (y : A). B y) (x : A). B x
と同じです
(∀ (y : A). B y) -> ∀ (x : A). B x
そしてapp ? ?受け取るもの
∀ (x : A'). B' x
これにより
A' ~ ∀ (y : A). B y
B' ~ λ _. ∀ (x : A). B x -- B' ignores its argument
(「偏見とは?」も参照)
私たちの表現(名前の変更後)は
∀ (A : *) (B : A -> *). ?
λ A B . app (∀ (x : A). B x) (λ _. ∀ (x : A). B x) (app A B)
のためにA、Bそしてf(where f ∈ ∀ (y : A). B y)
∀ (y : A). B y
app A B f
インスタンス化AしBて取得することができます(f適切なタイプの場合)
∀ (y : ∀ (x : A). B x). ∀ (x : A). B x
app (∀ (x : A). B x) (λ _. ∀ (x : A). B x) f
型の署名はと同等(∀ (x : A). B x) -> ∀ (x : A). B xです。
全体の表現は
∀ (A : *) (B : A -> *). (∀ (x : A). B x) -> ∀ (x : A). B x
λ A B . app (∀ (x : A). B x) (λ _. ∀ (x : A). B x) (app A B)
すなわち
∀ (A : *) (B : A -> *) (f : ∀ (x : A). B x) (x : A). B x
λ A B f x .
app (∀ (x : A). B x) (λ _. ∀ (x : A). B x) (app A B) f x
値レベルでのすべての削減の後、同じappバックが得られます。
そのためapp、取得する純粋なラムダ計算ではほんの数ステップしか必要ありませんがapp app、型付き設定(特に依存型付き)では、統一に注意する必要があります。* ∈ *ます。
型チェック
- 場合
tで*、その後t ∈ *で(1)
- 場合
tで∀ (x : σ) τ、σ ∈? *、τ ∈? *(約ノートを参照∈?その後、下記を)t ∈ *(2)により、
- 場合は
tあるf x、f ∈ ∀ (v : σ) τいくつかのためにσとτ、x ∈? σその後、t ∈ SUBS(τ, v, x)(4)によって
- if
tが変数でありv、それまでに(5)によってv導入された∀ (v : σ). τt ∈ σ
これらはすべて推論規則ですが、ラムダに対して同じことはできません(型の推論は依存型では決定できません)。したがって、ラムダについてt ∈? σは、推測ではなく()を確認します。
- で
tありλ v. b、チェックされている場合∀ (v : σ) τ、b ∈? τそして、t ∈ ∀ (v : σ) τ
- if
tが他のものであり、チェックされている場合は、上記の関数σをt使用するタイプを推測し、σ
型の等価性チェックでは、それらの型が通常の形式である必要があるため、型があるかどうかを判断するにtは、σまずtype を持つ型をチェックしσます*。もしそうなら、それσは正規化可能(モジュロジラールのパラドックス)であり、正規化σされます(したがって(0)で整形式になります)。SUBSまた、式を正規化して保持します(0)。
これは、双方向型チェックと呼ばれます。これにより、すべてのラムダに型の注釈を付ける必要がありません:f x型fが既知の場合、推論されて同等であるかどうか比較される代わりにx、引数の型に対してチェックされますf(これも非効率的です)。しかし、fがラムダである場合、明示的な型注釈が必要です(注釈は文法およびどこでも省略されます。追加Ann Term Termまたはλ' (σ : Term) (v : Var)。コンストラクタに、コンストラクタに)。
また、Simpler、Easierをご覧ください!ブログ投稿。