diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1b5e01e..4ed5787 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -22,5 +22,5 @@ - [型推論](./type_checking/type_inference.md) - [定義上の同値](./type_checking/definitional_equality.md) - [簡約](./type_checking/reduction.md) -- [Open issues & future work](./future_work.md) -- [Further reading](./further_reading.md) \ No newline at end of file +- [課題と今後の展望](./future_work.md) +- [その他の記事](./further_reading.md) \ No newline at end of file diff --git a/src/further_reading.md b/src/further_reading.md index 4d572ff..e28eb83 100644 --- a/src/further_reading.md +++ b/src/further_reading.md @@ -1,19 +1,51 @@ + +# その他の記事 + + + ++ Mario Carneiro による [Lean の型理論](https://github.com/digama0/lean-type-theory) + ++ Lean 公式カーネル:https://github.com/leanprover/lean4/tree/master/src/kernel + + + ++ [lean4lean](https://github.com/digama0/lean4lean/tree/master)、Lean 4 による Lean カーネルの再実装 + + ++ [lean4export](https://github.com/leanprover/lean4export)、Lean 4 環境のオフィシャル・推奨エクスポータ + [lean4checker](https://github.com/leanprover/lean4checker) + + ++ Peter Dybjer による Lean で実装される帰納型に関するオリジナルの記述:P. Dybjer. Inductive families. Formal aspects of computing, 6(4):440–465, 1994. + ++ Conor McBride と James McKinna の論文 [_I am not a number: I am a free variable_](http://www.e-pig.org/downloads/notanum.pdf) は束縛・自由変数への locally nameless なアプローチを記述しています。 + + + ++ 帰納型における positive ではない出現に関する情報、_Counterexamples in Type Systems_: https://counterexamples.org/strict-positivity.html?highlight=posi#positivity-strict-and-otherwise + Freek Wiedijk. Pollack-inconsistency. Electronic Notes in Theoretical Computer Science, 285:85–100, 2012 diff --git a/src/future_work.md b/src/future_work.md index 4edef8d..f10623f 100644 --- a/src/future_work.md +++ b/src/future_work.md @@ -1,25 +1,73 @@ + +# 課題と今後の展望 + + + +## ファイルフォーマット + + +エクスポートファイルのフォーマットをJSONに移行する件について、[こちら](https://github.com/leanprover/lean4export/issues/3) にオープンなRFCがあります。これは大きなバージョン変更になるでしょう。 + +## 整数・文字列が適切に定義されていることの確認 + + + +`Nat`・`String`・およびそれらに関連するカーネル拡張がカバーする操作のためのエクスポートファイルの宣言が、信頼されたコードにエクスポータを引き込まない方法で拡張が期待するものと一致するかどうかを判断するための特定の解決策について Lean コミュニティはまだ定まっていません。 + + +`Eq` と `Quot` の宣言のようなアプローチ(型チェッカ内で手作業で定義し、それらが同じであることを保証する)は `Nat` でサポートしているバイナリ演算のための完全にエラボレートされた項が複雑であるため実行不可能です。 + +## Pollack consistency の改善 + + + +Lean 4 はカスタム構文・マクロ・プリティプリンタの定義に非常に強力な機能を提供し、Lean 4 の内部のほとんどすべての側面がユーザによって利用可能です。Lean の設計のこれらの要素は Lean 3 の存続期間中に mathlib コミュニティから実際に寄せられたフィードバックに対する効果的な対応でした。 + + +これらの機能は大規模な形式化作業を可能にするツールとして Lean が成功した重要な要因である一方、Lean 4 の Pollack consistency[^pollack] が危うく、もしくは損なわれる恐れがあります。プリティプリンタでマクロと構文拡張機能を複製しなければ、型チェッカは一貫して項を認識可能な形で読んでユーザに返すことができません。しかし、これらの機能をプリティプリンタに追加するアイデアは信頼されたコードベースを拡張する点においては魅力的なものではありません。別のアプローチとしてプリティプリンタをやめて、信頼できるパーサ(通称 metamath zero)を採用する方法もありますが、Lean のパーサはカスタム構文宣言を使ってユーザ空間でその場で変更することができます。 + +Lean が成熟し、採用が進むにつれて Pollack consistency を犠牲にすることなく、ユーザが Lean の拡張性を活用できるような技術や手法の開発が進められるでしょう。 + + + +## 前方推論 + + +既存の型チェッカは後方推論の形式を実装しています;型チェッカの戦略の別路線として、外部プログラムによって作成された前方推論の連鎖を受け入れ、チェックすることがあり、これは後方推論よりもシンプルな型チェッカとなる可能性があります。 [^pollack]: Freek Wiedijk. Pollack-inconsistency. Electronic Notes in Theoretical Computer Science, 285:85–100, 2012 \ No newline at end of file diff --git a/src/type_checking/reduction.md b/src/type_checking/reduction.md index e53eebb..7422eb7 100644 --- a/src/type_checking/reduction.md +++ b/src/type_checking/reduction.md @@ -1,20 +1,30 @@ - + # 簡約 - + 簡約とは、式が定義上等しいかどうかを判定てきるように式を [正規形](https://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E5%8C%96_(%E9%A0%85%E6%9B%B8%E3%81%8D%E6%8F%9B%E3%81%88)) に近づけることです。例えば、`(fun x => x) Nat.zero` が `Nat.zero` と定義上等しいと判断するためにβ簡約を行い、`id List.nil` が `List.nil` と定義上等しいと判断するためにδ簡約を行う必要があります。 - + Lean のカーネルにおける簡約には2つの性質がありますが、この分野を扱う基本的な教科書では触れられない恐れがあります。まず、場合によっては簡約と推論が同時に行われることがあります。とりわけ、たとえ簡約によって自由変数が生成されなくとも、これは開いた項で簡約を実行する必要があるかもしれないことを意味しています。第二に、複数の引数に適用される `const` 式は(ι簡約のように)簡約を行う中でそれらの引数を一緒に考慮する必要がある場合があり、簡約開始時に一連の適用を一緒に展開する必要があります。 - + ## β簡約 - + β簡約は関数適用についての簡約です。具体的には、次の簡約です: @@ -22,7 +32,9 @@ Lean のカーネルにおける簡約には2つの性質がありますが、 (fun x => x) a ~~> a ``` - + β簡約の実装は `app` 式の引数を集め、それらが適用される式がラムダ式であるかどうかをチェックし、適切な引数を関数本体の対応する束縛変数の出現に置換するために式を手入れしなければなりません: @@ -36,7 +48,9 @@ betaReduceAux f args: | _, _ => foldApps f args ``` - + β簡約のインスタンス化(置換)コンポーネントの重要なパフォーマンス最適化は、「generalized beta reduction」と呼ばれるもので、対応するラムダ式を持つ引数を集め、それらを一度に置換する方法です。この最適化は、適用された引数を持つ `n` 個の連続したラムダ式に対して、`n` 回の走査ではなく、適切な引数を代入するための1回の走査のみを実行することを意味します。 @@ -50,11 +64,15 @@ betaReduceAux f remArgs argsToApply: | _, _ => foldApps (inst f argsToApply) remArgs ``` - + ## ζ簡約(`let` 式の簡約) - + ζ簡約は `let` 式の簡約を表す大仰な名前です。具体的には、次の簡約です: @@ -62,7 +80,9 @@ betaReduceAux f remArgs argsToApply: let (x : T) := y; x + 1 ~~> (y : T) + 1 ``` - + 実装はシンプルであり、ほぼ次と同じです: @@ -71,15 +91,21 @@ reduce Let _ val body: instantiate body val ``` - + ## δ簡約(定義の展開) - + δ簡約は定義(と定理)を展開することを指します。δ簡約は `const ..` 式について、その定義の多相宇宙パラメータを現在のコンテキストに関連した値で交換した後に、参照されている定義の値で置き換えることによって行われます。 - + 現在の環境に定義 `x` があり、その定義が宇宙パラメータ `u*` と値 `v` で宣言されている場合、式 `Const(x, w*)` を `val` で置き換えてδ簡約し、宇宙パラメータ `u*` を `w*` に置き換えます。 @@ -89,27 +115,39 @@ deltaReduce Const name levels: substituteLevels (e := v) (ks := d.uparams) (vs := levels) ``` - + δ簡約された `const` 式に到達するために、適用された引数を簡約しなければならなかった場合、それらの引数は簡約された定義に再適用されなければなりません。 - + ## 射影の簡約 - + `proj` 式は射影されるフィールドを表す自然数のインデックスと、構造体そのものを示す式を持ちます。構造体を構成する実際の式は、コンストラクタを参照する `const` に適用される一連の引き数でなければなりません。 - + ここで心に留めてもらいたいこととして、完全にエラボレートされた項に対して、コンストラクタの引数は任意のパラメータを含むため、`Prod` コンストラクタのインスタンスは例えば `Prod.mk A B (a : A) (b : B)` となります。 - + 射影されたフィールドを示す自然数は0始まりであり、0はコンストラクタの最初の **非パラメータ** 引数です。というのも射影は構造体のパラメータのアクセスに使うことができないからです。 - + これを念頭に置けば、コンストラクタの引数を `(constructor, [arg0, .., argN])` へと手直しすれば、射影の簡約は単純に `i + num_params` の位置にある引数を取るだけであることが明白になるでしょう。ここで `num_params` はその名前の通りのもので、その構造体型のパラメータの数を表します。 @@ -123,39 +161,57 @@ reduce proj fieldIdx structure: -- args will be `[A, B, a, b]` ``` - + ### 射影の特殊なケース:文字列リテラル - + カーネルは文字列リテラルについて拡張を行っており、これによって射影の簡約で1つ、ι簡約で1つの特殊なケースが導入されます。 - + 文字列リテラルに対する射影の簡約:なぜなら構造体の射影の式を簡約すると文字列リテラルになる可能性があるからです(Lean の `String` 型は `List Char` のフィールドを1つ持つ構造体として定義されています)。 - + もしその構造体が `StringLit (s)` に簡約される場合、これを `String.mk (.. : List Char)` に変換し、いつものように射影の簡約が処理されます。 - + ## 整数リテラルの簡約 - + 整数リテラル用のカーネル拡張には加算・減算・乗算・指数・除算・剰余・真偽値の同値・真偽値の以下の二項演算に加えて `Nat.succ` の簡約が含まれます。 - + 簡約される式が `Const(Nat.succ, []) n` で `n` が整数リテラル `n` に簡約できる場合、`NatLit(n'+1)` に簡約されます。 - + もし式が `Const(Nat., []) x y` へと簡約され `x` と `y` がそれぞれ整数リテラル `x'` と `y'` に簡約される場合、適切な `` のネイティブ版を `x'` と `y'` に適用し、結果の整数リテラルを返します。 - + 例: ``` @@ -166,27 +222,39 @@ Const(Nat.add, []) NatLit(2) NatLit(3) ~> NatLit(2+3) Const(Nat.add, []) (Const Nat.succ [], NatLit(10)) NatLit(3) ~> NatLit(11+3) ``` - + ## ι簡約(パターンマッチ) - + ι簡約とは与えられた帰納的宣言に特有でかつそこから派生した簡約戦略を適用することです。これはまさに帰納的宣言の再帰子(または後で説明する `Quot` の特別な場合)の適用です。 - + 各再帰子は「再帰子ルール」を持っており、各コンストラクタごとに1つの再帰子ルールがあります。型として表示される再帰子とは対照的に、これらの再帰子ルールはコンストラクタ `T.c` で作成された `T` 型の要素をどのように除去するかを示す値レベルの式です。例えば、`Nat.rec` は `Nat.zero` と `Nat.succ` それぞれに対する再帰子ルールを持ちます。 - + 帰納的宣言 `T` に対して、`T` の再帰子が要求する要素の1つは実際の `(t : T)` であり、これは除去する対象です。この `(t : T)` 引数は「major premise」と呼ばれます。ι簡約は major premise を分解することで `t` の構築にあたってどのコンストラクタが使われたかを確認し、対応する再帰子ルールを環境から取得して適用することでパターンマッチを行います。 - + 再帰子の型シグネチャは必要なパラメータ・motive・minor premiseも要求するため、例えば `Nat.succ` とは対照的に `Nat.zero` に対して簡約を実行するために再帰子の引数を変更する必要はありません。 - + 実際には major premise を作成するために使用されたコンストラクタを公開するための初期化的な手動操作が必要になることがあります。というのもこのコンストラクタがコンストラクタを直接適用したものとして見つからないことがあるからです。例えば、`NatLit(n)` 式は `Nat.zero` か `App Const(Nat.succ, []) ..` のいずれかに変換する必要があります。構造体では、構造体のη展開を行う場合もあります。要素 `(t : T)` を `T.mk t.1 .. t.N` に変換することで、`mk` コンストラクタの適用が明らかになり、ι簡約を進めることができます(major premise を作成するために使用されたコンストラクタが分からない場合、簡約は失敗します)。 @@ -225,51 +293,75 @@ fun ``` - + ### k-like 簡約 - + 「subsingleton eliminator」として知られているいくつかの帰納型では、major premise のコンストラクタが直接公開されていなくても、その型が分かっている限りι簡約を進めることができます。これは例えば major premise が自由変数として現れるような場合です。これは k-like 簡約と呼ばれ、subsingleton eliminator のすべての要素が同一であるため許容されます。 - + subsingleton eliminator であるためには、帰納的宣言は帰納的な命題でなければならず、また相互帰納的対象や入れ子の帰納的対象であってはならず、コンストラクタはちょうど1つでなければならず、その唯一のコンストラクタは型のパラメータだけを引数として取らなければなりません(型シグネチャで完全に捕捉されていない情報を「隠す」ことはできません)。 - + 例えば、`Eq Char 'x'` 型の要素の値はこの型のすべての要素は同一であるため、その型だけで完全に決定されます。 - + ι簡約によって subsingleton eliminator である major premise が見つかった場合、その major premise を型コンストラクタの適用に置換することが許容されます。なぜならその自由変数としてあり得るのがこの型コンストラクタだけだからです。例えば、`Eq Char 'a'` 型の自由変数である major premise は明示的に構成された `Eq.refl Char 'a'` に置換することができます。 - + 根本的な話として、もし k-like 簡約を探索して適用することを怠れば、subsingleton eliminator である自由変数は対応する再帰規則を特定できず、ι簡約は失敗し、成功すると期待されたある種の変換は成功しなくなるでしょう。 - + ### `Quot` の簡約;`Quot.ind` と `Quot.lift` - + `Quot` はカーネルでハンドルするべき2つの特殊なケースを導入します。1つは `Quot.ind` で、もう一つは `Quot.lift` の場合です。 - + `Quot.ind` と `Quot.lift` はどちらも関数 `f` の引数 `(a : α)` への適用に対応しており、ここで `a` は `Quot r` の構成要素であり、`Quot.mk .. a` によって形成されます。 - + この簡約を実行するには、`f` の要素である引数と、`(a : α)` が見つかる `Quot` 要素である引数を取り出し、`a` に関数 `f` を適用する必要があります。最後に、`Quot.ind` や `Quot.lift` の呼び出しとは関係のない外部式の一部であった引数を再適用します。 - + これは簡約のステップにすぎないため、式全体が適切に型付けされていることを保証するために他の場所で行われる型チェックの段階に頼ります。 - + 以下に `Quot.ind` と `Quot.mk` の型シグネチャを再作成し、テレスコープの要素を引数として見つけるべきものにマッピングしています。`*` が付いている要素は簡約のために必要なものです。 diff --git a/src/type_checking/type_inference.md b/src/type_checking/type_inference.md index d29f175..eecedb9 100644 --- a/src/type_checking/type_inference.md +++ b/src/type_checking/type_inference.md @@ -32,7 +32,7 @@ We will also look at a number of additional correctness assertions that Lean's k If you're following Lean's implementation and using the locally nameless approach, you should not run into bound variables during type inference, because all open binders will be instantiated with the appropriate free variables. --> -Lean の実装に従ってローカルに名前を持たないアプローチを使う場合、型推論中で束縛変数に遭遇することはないでしょう。というのもすべての開いた束縛子は適切な自由変数でインスタンス化されているからです。 +Lean の実装に従って locally nameless なアプローチを使う場合、型推論中で束縛変数に遭遇することはないでしょう。というのもすべての開いた束縛子は適切な自由変数でインスタンス化されているからです。