import FormalLab.TypeTheory.DependentTypes import FormalLab.TypeTheory.IdentityTypes import FormalLab.TypeTheory.IndexedFamilies /-! # 全問題の解答:依存型理論 ## 第31章:型族・依存関数型・依存対型 ### 問題1:定数族から通常の関数と対を復元する #### ヒント 型族 `B : A→Type` を `B a=C` という定数族にします。 #### 解答 依存関数型 `(a:A)→B a` でBが定数Cなら、返り値型は入力に依存せず通常の `A→C` です。依存対型 `(a:A)×B a` も通常の積 `A×C` になります。従ってΠ型とΣ型は関数型と積型を含む一般化です。ただし構文上の 定数族と定義的に同じか、同値を介して定数かは区別します。後者では明示的な輸送が必要な場合があります。 論理ではΠを全称量化、Σを証人を保持する存在として読み、非依存の場合との連続性を確認します。 ### 問題2:依存対を作り、添字に沿って除去する #### ヒント `Σn:Nat, Vector A n` の第一射影で長さ、第二射影でその長さのベクトルを得ます。 #### 解答 三要素ベクトル `v : Vector A 3` から `⟨3,v⟩ : Σn,Vector A n` を作れます。入力pを場合分けして `⟨n,xs⟩` とすれば、結果型の中でもnとxsの対応を保ったまま利用できます。例えば `xs` の長さを再び添える関数は `fun ⟨n,xs⟩ => ⟨n,xs⟩` です。第一射影だけを先に忘れると第二成分の型を記述できないため、依存消去は対を 一緒に開きます。 パーサが「長さとその長さの配列」を返すAPIでは、Σ型により整合性を返り値へ保存できます。 ### 問題3:論理的存在と計算データを比較する #### ヒント Leanの `Exists` はProp、`Sigma` はTypeに属することから消去先の違いを見ます。 #### 解答 `∃x:A,P x` は証明の存在を主張し、証明無関連性とPropからの消去制限の下で扱われます。`Σx:A,B x` は第一成分と 第二成分を計算データとして保持し、任意のTypeを返す関数で分解できます。存在証明から一般のプログラムとして証人を 抽出できるとは限りません。構成的証明が具体的な証人を作っていても、公開するインターフェースをPropにするかTypeに するかで利用可能性が変わります。 仕様の充足だけが必要なら命題、後続計算が証人を使うなら依存対というAPI設計基準にします。 ## 第32章:同一性型・輸送・外延性原理 ### 問題1:`J` から対称性と推移性を再構成する #### ヒント 等式証明を `refl` の場合へ帰着し、その場合の返り値を指定します。 #### 解答 対称性は `p:x=y` を消去し、目標 `y=x` を `x=x` へ帰着して `refl x` を返します。推移性は `p:x=y` を消去した後、`q:y=z` が `q:x=z` となるのでqを返せます。どちらも等式の唯一の導入子reflに対する 場合を与えたJの特殊化です。等式連鎖の法則も等式証明へ帰納すればreflの場合の計算へ還元されます。 輸送、合同性、置換原理をすべてJから導き、どれをライブラリの基本APIにするか比較します。 ### 問題2:ベクトルの長さ等式に沿って輸送する #### ヒント 型族 `P(k)=Vector A k` に等式 `p:n=m` を使います。 #### 解答 `v:Vector A n` と `p:n=m` から `transport P p v : Vector A m` を得ます。pがreflなら輸送結果は定義的にvです。 一般のpではデータの要素を変更せず、型が参照する添字だけを同一視に沿って替えます。`n+0=n` の証明で `Vector A (n+0)` を `Vector A n` へ直す例では、等式の向きに応じてpまたは対称性pを選びます。 圏の対象等式に沿う射の型変更など、依存する構造を添字同一視に沿って移す操作へ一般化します。 ### 問題3:四つの外延性原理を比較する #### ヒント 命題外延性、関数外延性、商健全性、一価性がどの種類の同値を等式へ送るかを書きます。 #### 解答 命題外延性は `P↔Q` から `P=Q`、関数外延性は `∀x,f x=g x` から `f=g` を与えます。商健全性は基礎関係 `r a b` を商内の等式へ送ります。一価性は型同値 `A≃B` を宇宙内の等式 `A=B` と対応させます。対象の層は 命題、関数、商の代表、型と異なり、互いを名前だけで代用できません。Leanでどれが定理・公理・商構成の規則かも 区別します。 外延的な数学を形式化するときは必要な等式原理を最小限にし、計算可能性への影響を記録します。 ## 第33章:純粋型システム・ラムダ・キューブ・構成計算 ### 問題1:PTSの規則から依存の許可範囲を読む #### ヒント 積形成規則 `(s₁,s₂,s₃)` が、どのソートの項へ依存する型をどのソートに作るかを表します。 #### 解答 PTSはソート、基礎公理 `s₁:s₂`、積形成三つ組で指定されます。規則 `(s₁,s₂,s₃)` があれば、 `Γ⊢A:s₁` と `Γ,x:A⊢B:s₂` から `Γ⊢Πx:A.B:s₃` を作れます。したがって依存の可否はΠの見た目ではなく この三つ組により決まります。項から項、型から項、項から型、型から型という二軸を分類すると、ラムダ・キューブの 各頂点を復元できます。 新しい型理論を比較するときは表面構文ではなく、宇宙公理とΠ形成規則の差として整理します。 ### 問題2:ラムダ・キューブを暗記せず復元する #### ヒント 単純型付きラムダ計算から、三種類の依存を独立なスイッチとして加えます。 #### 解答 三軸は項に依存する型、型に依存する項である多相性、型に依存する型である型演算子です。スイッチなしが 単純型付きラムダ計算、各一軸を加えた体系、その組合せ四つで八頂点になります。全軸を許す頂点が構成計算であり、 依存型とインプレディカティブな命題を統合する基礎になります。頂点名を暗記するより、許されるΠ型の例を一つずつ 作れば位置を再構成できます。 宇宙階層や帰納型は元の三軸に含まれないため、現代の証明支援系をキューブだけで分類し尽くさないようにします。 ### 問題3:体系の規則とメタ定理を切り分ける #### ヒント 判断を生成する規則と、その規則すべてについて外側から証明する性質を分けます。 #### 解答 変数・Π形成・抽象・適用・変換は体系内部の型付け規則です。弱化・代入・主部簡約は構文に関するメタ定理です。 型保存・強正規化・無矛盾性も規則から証明するメタ定理です。例えば変換規則があることと変換可能性が決定可能であることは別です。後者には 正規化や合流性が必要です。メタ定理を規則として無条件に追加すると、循環した「証明」になり得ます。 Leanのカーネル機能と、Lean自身について外部で証明・検証される健全性主張を同じ基準で区別します。 ## 第34章:部分型と篩型 ### 問題1:値と性質を一つの項として構成する #### ヒント 自然数nと証明 `n<5` を部分型の構成子へ同時に渡します。 #### 解答 `BelowFive := {n : Nat // n < 5}` とすると、`⟨3, by decide⟩ : BelowFive` です。第一射影 `.val` は3、第二射影 `.property` は `3<5` の証明です。二つの値 `x y : BelowFive` の等しさには、基礎値 `x.val=y.val` を示せば 部分型外延性を使えます。証明成分を個別に比較する必要がないのは、命題の証明無関連性によります。 正規化済み構文、範囲内添字、単調関数など、値と不変条件を同じAPI境界で受け渡せます。 #### 補足 部分型上の演算では、第一成分の値と、結果が再び述語を満たす第二成分を別々に構成します。正の自然数同士の加算なら 値は通常の加算で作り、正値性は入力の証明から示します。空な部分型を示すときは候補値の探索ではなく、任意の候補に 要求される証明成分が矛盾することを示します。専用帰納型では不変条件を構成子の形で保つため、同じ性質でも除去原理と 定義的計算が変わります。 ### 問題2:検査から精密な型へ移す #### ヒント ブール値だけでなく、成功時に境界証明を含む `Option` を返します。 #### 解答 `checkBelow (b n : Nat) : Option {k : Nat // k < b}` を、`if h:n Fin (n + 1)) : Nat := value.1 def payloadFromSigma (value : Sigma fun n : Nat => Fin (n + 1)) : Fin (value.1 + 1) := value.2 example : witnessFromSigma ⟨2, 1⟩ = 2 := rfl end FormalLab.Appendix.Solutions.Chapter031Exercise003 namespace FormalLab.Appendix.Solutions.Chapter032Exercise003 #check funext #check propext #check Subsingleton.elim end FormalLab.Appendix.Solutions.Chapter032Exercise003 namespace FormalLab.Appendix.Solutions.Chapter035Exercise003 open FormalLab.TypeTheory.IndexedFamilies def ListVector (α : Type) (n : Nat) := {items : List α // items.length = n} def mapListVector (function : α → β) (items : ListVector α n) : ListVector β n := ⟨items.1.map function, by simpa using items.2⟩ def mapIndexedVector (function : α → β) (items : FormalLab.TypeTheory.IndexedFamilies.Vector α n) : FormalLab.TypeTheory.IndexedFamilies.Vector β n := map function items end FormalLab.Appendix.Solutions.Chapter035Exercise003 namespace FormalLab.Appendix.Solutions.Chapter034Exercise001 abbrev Positive := {n : Nat // 0 < n} def addPositive (left right : Positive) : Positive := ⟨left.1 + right.1, by omega⟩ example : (addPositive ⟨2, by decide⟩ ⟨3, by decide⟩).1 = 5 := rfl theorem noNegativeNatural (impossible : {n : Nat // n < 0}) : False := by omega end FormalLab.Appendix.Solutions.Chapter034Exercise001