h5i

第 9 章

等式も帰納型である

0+n=n0 + n = n のような数に関する事実を述べるには、等しさを表す手段が要る。専用の規則がカーネルに組み込まれているように思えるかもしれないが、等式も第 8 章の手順で生成される帰納型の一つであり、その再帰子を使えば、aa についての事実を bb についての事実へ移せる。本章ではこの型を宣言し、定義的等価との違いを説明してから、本書で最初の本格的な定理を証明する。

宣言

Lean では、等式は次のように宣言されている。

inductive Eq {A : Sort u} (a : A) : A -> Prop where
  | refl : Eq a a

a,b:Aa, b : A に対して、型 Equ  A  a  b\Eq{u}\;A\;a\;b は aa と bb が等しいという命題である。AA が Nat\Nat のときは a=ba = b と書く。第 8 章の言葉でいえば、AA と aa がパラメータで bb が添字である。

Equ:Π(A:Sort u). A→A→Sort 0,reflu:Π(A:Sort u). Π(a:A). Equ  A  a  a.\Eq{u} : \tPi{A}{\Sort{u}}{A \to A \to \Sort{0}}, \qquad \refl{u} : \tPi{A}{\Sort{u}}{\tPi{a}{A}{\Eq{u}\;A\;a\;a}}.

唯一の構成子 reflu\refl{u} はフィールドを持たず、その添字項は aa なので、両辺が同じ aa である等式しか証明できない。したがって Eq\Eq{} は単一の型ではなく Vec\mathsf{Vec} と同じ帰納族であり、左辺はパラメータで固定され、右辺は変化するが、構成子がそれを左辺に釘付けにする。

再帰子: 輸送

くだけて言えば、Eq\Eq{} の再帰子はこう述べている。a=ba = b ならば、aa について成り立つことは何であれ bb についても成り立つ。 これはライプニッツの原理であり、最もよく使われる形では次のように読める。

Eq.ndrecu,v:Π(A:Sort u). Π(a:A). Π(M:A→Sort v). M  a→Π(b:A). Equ  A  a  b→M  b.\EqRec{u,v} : \tPi{A}{\Sort{u}}{\tPi{a}{A}{\tPi{M}{A \to \Sort{v}}{M\;a \to \tPi{b}{A}{\Eq{u}\;A\;a\;b \to M\;b}}}}.

AA の要素についての性質 MM、証拠 m:M  am : M\;a、そして a=ba = b の証明 hh が与えられると、M  bM\;b の証拠を返す。mm を hh に沿って輸送(transport)する、という。その計算規則は、refl\refl{} に沿った輸送は何もしない、というものである。

Eq.ndrecu,v  A  a  M  m  b  (reflu  A  c)  →  m.\EqRec{u,v}\;A\;a\;M\;m\;b\;(\refl{u}\;A\;c) \;\to\; m.

第 8 章の一般的な手順が生成するものはこれより少し一般的で、Eq.ndrec\EqRec{} はそれから組み立てた定義である。

手順が生成する完全な依存再帰子

bb は添字なので、motive は bb と証明 h:Equ  A  a  bh : \Eq{u}\;A\;a\;b を受け取る。小前提は reflu\refl{u} のための一つだけで、フィールドも仮定もない。

Eq.recu,v:Π(A:Sort u). Π(a:A). Π(M:(Π(b:A). Equ  A  a  b→Sort v)). M  a  (reflu  A  a)→Π(b:A). Π(h:Equ  A  a  b). M  b  hEq.recu,v  A  a  M  m  b  (reflu  A′  c)  →ι  m.\begin{array}{l} \EqRecDep{u,v} : \tPi{A}{\Sort{u}}{\tPi{a}{A}{\tPi{M}{(\tPi{b}{A}{\Eq{u}\;A\;a\;b \to \Sort{v}})}{{}}}} \\[2pt] \qquad\qquad M\;a\;(\refl{u}\;A\;a) \to \tPi{b}{A}{\tPi{h}{\Eq{u}\;A\;a\;b}{M\;b\;h}} \\[8pt] \EqRecDep{u,v}\;A\;a\;M\;m\;b\;(\refl{u}\;A'\;c) \;\iotared\; m. \end{array}

Eq\Eq{} は部分単集合(構成子が一つでフィールドなし)なので vv は任意でよく、等式の証明は、証明だけでなくデータを組み立てるのにも使える。非依存の Eq.ndrecu,v\EqRec{u,v} は、motive が証明を無視する特殊な場合である。

Eq.ndrecu,v:=λ(A:Sort u). λ(a:A). λ(M:A→Sort v). λ(m:M  a). λ(b:A). λ(h:Equ  A  a  b). Eq.recu,v  A  a  (λ(b′:A). λ(_:Equ  A  a  b′). M  b′)  m  b  h.\begin{array}{l} \EqRec{u,v} \mathrel{:=} \tLam{A}{\Sort{u}}{\tLam{a}{A}{\tLam{M}{A \to \Sort{v}}{\tLam{m}{M\;a}{\tLam{b}{A}{\tLam{h}{\Eq{u}\;A\;a\;b}{{}}}}}}} \\[2pt] \qquad\qquad \EqRecDep{u,v}\;A\;a\;(\tLam{b'}{A}{\tLam{\_}{\Eq{u}\;A\;a\;b'}{M\;b'}})\;m\;b\;h. \end{array}

型の付いた簡約基では bb も cc も aa と変換可能なので、規則はそれらを無視してよい。図 9.1 にこれらの定数をまとめる。

図 9.1. 等式のための定数とその計算規則。Eq.ndrecu,v\EqRec{u,v} の規則は、その定義から δ、β、および Eq.recu,v\EqRecDep{u,v} の規則によって従う。

Equ:Π(A:Sort u). A→A→Sort 0Lean: Eqreflu:Π(A:Sort u). Π(a:A). Equ  A  a  aEq.reflEq.recu,v:Π(A:Sort u). Π(a:A). Π(M:(Π(b:A). Equ  A  a  b→Sort v)). M  a  (reflu  A  a)→Π(b:A). Π(h:Equ  A  a  b). M  b  hEq.recEq.ndrecu,v:Π(A:Sort u). Π(a:A). Π(M:A→Sort v). M  a→Π(b:A). Equ  A  a  b→M  bEq.ndrec (definition)\begin{array}{lcll} \Eq{u} &:& \tPi{A}{\Sort{u}}{A \to A \to \Sort{0}} & \text{Lean: } \texttt{Eq} \\[2pt] \refl{u} &:& \tPi{A}{\Sort{u}}{\tPi{a}{A}{\Eq{u}\;A\;a\;a}} & \texttt{Eq.refl} \\[2pt] \EqRecDep{u,v} &:& \tPi{A}{\Sort{u}}{\tPi{a}{A}{\tPi{M}{(\tPi{b}{A}{\Eq{u}\;A\;a\;b \to \Sort{v}})}{M\;a\;(\refl{u}\;A\;a) \to \tPi{b}{A}{\tPi{h}{\Eq{u}\;A\;a\;b}{M\;b\;h}}}}} & \texttt{Eq.rec} \\[2pt] \EqRec{u,v} &:& \tPi{A}{\Sort{u}}{\tPi{a}{A}{\tPi{M}{A \to \Sort{v}}{M\;a \to \tPi{b}{A}{\Eq{u}\;A\;a\;b \to M\;b}}}} & \texttt{Eq.ndrec}\ \text{(definition)} \end{array}
Eq.recu,v  A  a  M  m  b  (reflu  A  c)→ιmEq.ndrecu,v  A  a  M  m  b  (reflu  A  c)→δβιm\begin{array}{rcl} \EqRecDep{u,v}\;A\;a\;M\;m\;b\;(\refl{u}\;A\;c) &\iotared& m \\[2pt] \EqRec{u,v}\;A\;a\;M\;m\;b\;(\refl{u}\;A\;c) &\to_{\delta\beta\iota}& m \end{array}

たとえば P:Nat→Sort 0P : \Nat \to \Sort{0}、a,b:Nata, b : \Nat、h:a=bh : a = b、pa:P  a\mathit{pa} : P\;a とする。motive M=PM = P を選ぶと

Eq.ndrec1,0  Nat  a  P  pa  b  h  :  P  b.\EqRec{1,0}\;\Nat\;a\;P\;\mathit{pa}\;b\;h \;:\; P\;b.

この一行が書き換えの論理的な中身であり、aa についての事実が bb についての事実になる。第 10 章の rw タクティクは、このような項を自動で組み立てる。

定義的等価と命題的等価

いまや等しさの概念が二つあり、この二つを区別することが、証明支援系の振る舞いを理解するうえで欠かせない。

  • 定義的等価 ≡\conv は、カーネルが計算によって決定する。項についての判断であって型ではなく、証明オブジェクトは関与しない。
  • 命題的等価 Eq\Eq{} は型であり、その証明は項で、見つけるには帰納法のような本物の推論が要ることがある。

構成子 refl\refl{} が両者をつなぐ。T-Conv により、a≡ba \conv b であれば常に reflu  A  a:Equ  A  a  b\refl{u}\;A\;a : \Eq{u}\;A\;a\;b となるので、定義的等価からは命題的等価がただで得られるが、逆は成り立たない。標準的な例が n+0=nn + 0 = n と 0+n=n0 + n = n の二つである。第 7 章の add\add の定義を使い、その段階関数を ss とすると、

n+0  →δβ  Nat.rec1  (λ(_:Nat). Nat)  n  s  zero  →ι  n,n + 0 \;\to_{\delta\beta}\; \NatRec{1}\;(\tLam{\_}{\Nat}{\Nat})\;n\;s\;\zero \;\iotared\; n,

なので refl1  Nat  n:n+0=n\refl{1}\;\Nat\;n : n + 0 = n であり、Lean はこれを rfl で証明する。対照的に、

0+n  →δβ  Nat.rec1  (λ(_:Nat). Nat)  0  s  n0 + n \;\to_{\delta\beta}\; \NatRec{1}\;(\tLam{\_}{\Nat}{\Nat})\;0\;s\;n

は行き詰まる(stuck)。nn は変数であり、ι 規則は zero\zero と succ\suc に対してしか発火しないので、0+n=n0 + n = n は refl\refl{} では証明できず、帰納法が要る。

簡約エクスプローラは、文脈に変数 nn を置いて両方の計算を示す。前者は nn に到達する一方、後者は、来るはずのない構成子を再帰子が待ったまま止まる。

def add : Nat -> Nat -> Nat := fun (m : Nat) => fun (n : Nat) => Nat.rec1 (fun (_n : Nat) => Nat) m (fun (k : Nat) => fun (r : Nat) => Nat.succ r) n
def add : Nat -> Nat -> Nat := fun (m : Nat) => fun (n : Nat) => Nat.rec1 (fun (_n : Nat) => Nat) m (fun (k : Nat) => fun (r : Nat) => Nat.succ r) n
def add : Nat -> Nat -> Nat := fun (m : Nat) => fun (n : Nat) => Nat.rec1 (fun (_n : Nat) => Nat) m (fun (k : Nat) => fun (r : Nat) => Nat.succ r) n

# n + 0 = n は計算で成り立つ: 再帰子は構成子 zero を見る。
goal forall (n : Nat), Eq Nat (add n Nat.zero) n
intro n
rfl
qed

# 0 + n = n はそうならない: 再帰子は変数 n で行き詰まる。
goal forall (n : Nat), Eq Nat (add Nat.zero n) n
intro n
rfl

例: 0 + n = n の証明

Π(n:Nat). 0+n=n\tPi{n}{\Nat}{0 + n = n} を帰納法で証明するのに、Nat.rec0\NatRec{0} を motive M0=λ(n:Nat). 0+n=nM_0 = \tLam{n}{\Nat}{0 + n = n} で使う。

基底。 必要なのは M0  0M_0\;0 で、これは 0+0=00 + 0 = 0 と変換可能であり、0+00 + 0 は 00 に計算されるので、項 refl1  Nat  0\refl{1}\;\Nat\;0 で済む。

ステップ。 k:Natk : \Nat と ih:0+k=k\mathit{ih} : 0 + k = k が与えられたとき、必要なのは M0  (succ  k)M_0\;(\suc\;k)、すなわち 0+succ  k=succ  k0 + \suc\;k = \suc\;k である。第二の ι 規則により 0+succ  k0 + \suc\;k は succ  (0+k)\suc\;(0 + k) に計算されるので、succ  (0+k)=succ  k\suc\;(0 + k) = \suc\;k を証明すれば足りる。succ  (0+k)=succ  (0+k)\suc\;(0+k) = \suc\;(0+k) の証明 refl1  Nat  (succ  (0+k))\refl{1}\;\Nat\;(\suc\;(0 + k)) から出発し、motive N=λ(b:Nat). succ  (0+k)=succ  bN = \tLam{b}{\Nat}{\suc\;(0 + k) = \suc\;b} で ih\mathit{ih} に沿って輸送する。この motive は二つ目の 0+k0 + k を kk に置き換える。

step=λ(k:Nat). λ(ih:0+k=k). Eq.ndrec1,0  Nat  (0+k)  N  (refl1  Nat  (succ  (0+k)))  k  ih.\mathit{step} = \tLam{k}{\Nat}{\tLam{\mathit{ih}}{0 + k = k}{ \EqRec{1,0}\;\Nat\;(0 + k)\;N\;(\refl{1}\;\Nat\;(\suc\;(0 + k)))\;k\;\mathit{ih}}}.

証明は次のとおりである。

zero_add=Nat.rec0  M0  (refl1  Nat  0)  step  :  Π(n:Nat). 0+n=n.\mathit{zero\_add} = \NatRec{0}\;M_0\;(\refl{1}\;\Nat\;0)\;\mathit{step} \;:\; \tPi{n}{\Nat}{0 + n = n}.

カーネルはこれをアルゴリズム 5.1 で検査し、各引数は、M0M_0 でインスタンス化した Nat.rec0\NatRec{0} の型の対応する部分に対して検査され、どの比較も正規化のあとで成功する。完全な項を、カーネルに一度に提出する形で示し、非依存再帰子は図 9.1 のとおり先に定義しておく。

def add : Nat -> Nat -> Nat := fun (m : Nat) => fun (n : Nat) => Nat.rec1 (fun (_n : Nat) => Nat) m (fun (k : Nat) => fun (r : Nat) => Nat.succ r) n

# レベル (1, 0) の Eq.ndrec: M a の証明を a = b に沿って M b へ輸送する。
def ndrec : forall (A : Sort 1), forall (a : A), forall (M : A -> Sort 0), M a -> forall (b : A), Eq A a b -> M b := fun (A : Sort 1) => fun (a : A) => fun (M : A -> Sort 0) => fun (m : M a) => fun (b : A) => fun (h : Eq A a b) => Eq.rec0 A a (fun (b' : A) => fun (_h : Eq A a b') => M b') m b h

goal forall (n : Nat), Eq Nat (add Nat.zero n) n
exact Nat.rec0 (fun (n : Nat) => Eq Nat (add Nat.zero n) n) (Eq.refl Nat Nat.zero) (fun (k : Nat) => fun (ih : Eq Nat (add Nat.zero k) k) => ndrec Nat (add Nat.zero k) (fun (b : Nat) => Eq Nat (Nat.succ (add Nat.zero k)) (Nat.succ b)) (Eq.refl Nat (Nat.succ (add Nat.zero k))) k ih)
qed

こうした項を手で書くのは手間がかかり、とくに正しい motive を見つけるのが難しい。motive NN は、0+k0 + k が現れる二箇所のうち、ちょうど一方だけで bb に言及しなければならなかった。タクティク(第 10 章)は、項の組み立てと motive の選択を自動化する。

カーネルへの変更

命題論理から等式付きの算術に進むのに、変更はわずかで済んだ。Infer\Infer には定数のケースが加わって Σ\Sigma から型を引く(T-Const)一方、Check\Check は変わらない。新しい δ ステップと ι ステップを覚えたのは Whnf\Whnf だけで、それを通して IsDefEq\IsDefEq も変わった。第 12 章では一つの Whnf\Whnf がすべての帰納型を扱う仕組みを示し、第 14 章では帰納型がメタ理論にもたらす変化を論じる。

演習

等式の対称性を証明せよ。Eq.ndrec\EqRec{} を使って型 Π(a:Nat). Π(b:Nat). a=b→b=a\tPi{a}{\Nat}{\tPi{b}{\Nat}{a = b \to b = a}} の項を組み立てよ。

解答

証明 refl  a:a=a\refl{}\;a : a = a を、motive λ(x:Nat). x=a\tLam{x}{\Nat}{x = a} で h:a=bh : a = b に沿って輸送すると、a=aa = a が b=ab = a に変わる。 λ(a:Nat). λ(b:Nat). λ(h:a=b). Eq.ndrec1,0  Nat  a  (λ(x:Nat). x=a)  (refl1  Nat  a)  b  h\tLam{a}{\Nat}{\tLam{b}{\Nat}{\tLam{h}{a = b}{\EqRec{1,0}\;\Nat\;a\;(\tLam{x}{\Nat}{x = a})\;(\refl{1}\;\Nat\;a)\;b\;h}}}。

goal forall (a : Nat), forall (b : Nat), Eq Nat a b -> Eq Nat b a
exact fun (a : Nat) => fun (b : Nat) => fun (h : Eq Nat a b) => ndrec Nat a (fun (x : Nat) => Eq Nat x a) (Eq.refl Nat a) b h
qed

(ndrec は上のプレイグラウンドのとおり定義しておく。)

Eq\Eq{} は命題であるのにすべての宇宙へ消去できる一方、構成子が二つある型 Or はそうではない。理由を説明せよ。

解答

Eq\Eq{} は部分単集合であり、構成子は一つで、フィールドはない。そのような証明の組み立て方が一通りしかないので、その再帰子で定義した関数は a=ba = b の二つの証明を区別できない。Or には構成子が二つあるので、Nat\Nat への再帰子は二つの注入に対して異なる数を返せてしまい、プログラムの値がどちらの証明が与えられたかに依存することになる。第 8 章にこの規則の正確な形がある。

覚えておくこと

  • Eq\Eq{} は、パラメータ AA と aa、添字 bb、フィールドを持たない唯一の構成子 refl\refl{} からなる帰納族である。
  • その再帰子は、a=ba = b の証明に沿って aa についての事実を bb についての事実へ輸送し、refl\refl{} に対しては何もしない。これが書き換えである。
  • 定義的等価は計算で決定される一方、命題的等価は型であり、その証明には帰納法が要ることがある。refl\refl{} が前者を後者に変える。
  • 加法が第二引数で再帰するので、n+0=nn + 0 = n は定義的で 0+n=n0 + n = n はそうでない。