From a26b2da10741e49492813f25405a4c0e493ab111 Mon Sep 17 00:00:00 2001 From: s-taiga Date: Thu, 15 Aug 2024 22:40:18 +0900 Subject: [PATCH] =?UTF-8?q?=E7=BF=BB=E8=A8=B3=E5=AE=8C=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../indices-parameters-universes.md | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/functional-programming-lean/src/dependent-types/indices-parameters-universes.md b/functional-programming-lean/src/dependent-types/indices-parameters-universes.md index 2c31e270..1dbede4a 100644 --- a/functional-programming-lean/src/dependent-types/indices-parameters-universes.md +++ b/functional-programming-lean/src/dependent-types/indices-parameters-universes.md @@ -1,55 +1,99 @@ - + # 添字、パラメータ、宇宙レベル + +帰納型の添字とパラメータの区別は、単にコンストラクタ間で型への引数が変化するか、もしくはしないかを記述する方法だけにとどまりません。帰納型の引数がパラメータか添字かは、それらの宇宙レベル間の関係を決定するときに重要になります。特に、帰納型はパラメータと同じ宇宙レベルを持つことが可能ですが、添字に対しては宇宙レベルは大きくなければなりません。この制約はLeanがプログラミング言語としてだけでなく、定理証明器としても使用できるようにするために必要です。こうしなければLeanの論理は一貫性が無くなることでしょう。型に対する引数がパラメータと添字のどちらにするべきかを決定する正確なルールと共に、これらのルールを説明するにはエラーメッセージを使って実験するのは良い方法です。 + + + +一般的に、帰納型の定義ではパラメータはコロンの前、添字はコロンの後に取られます。パラメータには関数の引数のように名前が与えられる一方、添字には型のみが記述されます。これは `Vect` の定義で見ることができます: + ```lean {{#example_decl Examples/DependentTypes.lean Vect}} ``` + +この定義では、`α` はパラメータで `Nat` は添字です。パラメータは定義全体を通して参照することができますが(例えば、`Vect.cons` は第一引数の型として `α` を使用しています)、それらは常に一貫使用される必要があります。添字は変更されることが期待されるため、データ型の定義の先頭で引数として提供されるのではなく、コンストラクタごとに個別の値が割り当てられます。 + + +パラメータを使った非常にシンプルなデータ型として次の `WithParameter` を考えます: + ```lean {{#example_decl Examples/DependentTypes/IndicesParameters.lean WithParameter}} ``` + + +宇宙レベル `u` は、パラメータと帰納型自体の両方に使用することができ、これはパラメータがデータ型の宇宙レベルを増大させないことを示します。同様に、複数のパラメータがある場合、帰納型はどちらか大きい方の宇宙レベルを受け取ります: + ```lean {{#example_decl Examples/DependentTypes/IndicesParameters.lean WithTwoParameters}} ``` + + +パラメータはデータ型の宇宙レベルを増加させないため、より便利に扱うことができます。Leanは添字のように(コロンの後に)記述されるがパラメータのように用いられる引数を識別し、それらをパラメータに変えようとします:以下の帰納的データ型はどちらもコロンの後にパラメータが記述されています: + ```lean {{#example_decl Examples/DependentTypes/IndicesParameters.lean WithParameterAfterColon}} {{#example_decl Examples/DependentTypes/IndicesParameters.lean WithParameterAfterColon2}} ``` + + +最初のデータ型の宣言でパラメータに名前が付けられていない場合、一貫して使用される限り各コンストラクタで異なる名前を使用しても良いです。次の宣言はLeanに受け入れられます: + ```lean {{#example_decl Examples/DependentTypes/IndicesParameters.lean WithParameterAfterColonDifferentNames}} ``` + + +しかし、この柔軟性は、パラメータの名前を明示的に宣言するデータ型には適用されません: + ```lean {{#example_in Examples/DependentTypes/IndicesParameters.lean WithParameterBeforeColonDifferentNames}} ``` ```output error {{#example_out Examples/DependentTypes/IndicesParameters.lean WithParameterBeforeColonDifferentNames}} ``` + + +同様に、添字に名前を付けようとするとエラーになります: + ```lean {{#example_in Examples/DependentTypes/IndicesParameters.lean WithNamedIndex}} ``` @@ -57,14 +101,24 @@ Similarly, attempting to name an index results in an error: {{#example_out Examples/DependentTypes/IndicesParameters.lean WithNamedIndex}} ``` + + +適切な宇宙レベルを用い添字をコロンの後ろに置くことで、Leanに許容される宣言となります: + ```lean {{#example_decl Examples/DependentTypes/IndicesParameters.lean WithIndex}} ``` + + +帰納型の宣言においてコロンの後にある引数がすべてのコンストラクタで一貫して使用されていればパラメータであるとLeanが判断できる場合もありますが、それでもすべてのパラメータはすべての添字より前に来る必要があります。添字の後にパラメータを置こうとすると、引数自体が添字と見なされ、データ型の宇宙レベルを上げる必要があります: + ```lean {{#example_in Examples/DependentTypes/IndicesParameters.lean ParamAfterIndex}} ``` @@ -72,15 +126,25 @@ Attempting to place a parameter after an index results in the argument being con {{#example_out Examples/DependentTypes/IndicesParameters.lean ParamAfterIndex}} ``` + + +パラメータは型である必要はありません。次の例は `Nat` のような通常のデータ型をパラメータとして使用できることを示しています: + ```lean {{#example_in Examples/DependentTypes/IndicesParameters.lean NatParamFour}} ``` ```output error {{#example_out Examples/DependentTypes/IndicesParameters.lean NatParamFour}} ``` + + +エラーメッセージの通りに `n` を使用すると、宣言が受理されます: + ```lean {{#example_decl Examples/DependentTypes/IndicesParameters.lean NatParam}} ``` @@ -88,15 +152,37 @@ Using the `n` as suggested causes the declaration to be accepted: + + +これらの実験から何が結論付けられるでしょうか?パラメータと添字のルールは以下の通りです: + + + 1. パラメータは各コンストラクタの型で同じものを使用しなければなりません。 + + 2. すべてのパラメータはすべての添字より前に来なければなりません。 + + 3. 定義されるデータ型の宇宙レベルは最も低くても最大のパラメータのものと同じ大きさでなければならず、最大の添字より大きくなければなりません。 + + 4. コロンの前に書かれた名前付きの引数は常にパラメータであり、コロンの後ろに書かれた引数は通常は添字です。コロンの後ろにある引数が一貫して使われ、かつ添字より後ろに来ないように使われている場合、それらをパラメータに変更するよう判断できます。 + + +どれがパラメータであるかわからない場合は、Leanのコマンド `#print` を使ってデータ型の引き数のうちいくつがパラメータなのかをチェックすることができます。例えば、`Vect` の場合、パラメータ数が1であることが示されます: + ```lean {{#example_in Examples/DependentTypes/IndicesParameters.lean printVect}} ``` @@ -104,9 +190,17 @@ For example, for `Vect`, it points out that the number of parameters is 1: {{#example_out Examples/DependentTypes/IndicesParameters.lean printVect}} ``` + + +データ型の引き数の順番を決める際に、どの引数をパラメータにし、どの引数を添字にするかを考えることには価値があります。可能な限り多くの引数をパラメータにすることは宇宙レベルを制御し、複雑なプログラムの型チェックを容易にすることができます。これを可能にする1つの方法は、引数リストにおいてすべてのパラメータがすべての添字の前に来るようにすることです。 + + +さらに、Leanはコロンの後にある引数がなんであろうともその使われ方からパラメータであることを判断することができますが、パラメータを明示的な名前で書くことは良い考え方です。こうすることで読み手に意図が明確に伝わ子、コンストラクタ間で引数が誤って一貫しない使われ方をした際にLeanがエラーを報告するようになります。