changeset 45:12c5e455fe55

Writing description proofs of monad-laws for delta
author Yasutaka Higa <e115763@ie.u-ryukyu.ac.jp>
date Sun, 15 Feb 2015 10:33:47 +0900
parents 4f1107f1f6aa
children 1b688e70f2a8
files Makefile agda.tex proof_delta.tex replace_agda.rb src/delta_association_law.agda src/delta_eta_is_nt.agda src/delta_left_unity_law.agda src/delta_monad_in_agda.agda src/delta_mu_is_nt.agda src/delta_right_unity_law.agda
diffstat 10 files changed, 235 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Fri Feb 13 18:10:07 2015 +0900
+++ b/Makefile	Sun Feb 15 10:33:47 2015 +0900
@@ -6,6 +6,7 @@
 	dvipdfmx $<
 
 $(TARGET).dvi : $(wildcard *.tex) $(wildcard fig/*.pdf)
+	ruby replace_agda.rb
 	platex $(TARGET).tex
 	platex $(TARGET).tex
 	platex $(TARGET).tex
--- a/agda.tex	Fri Feb 13 18:10:07 2015 +0900
+++ b/agda.tex	Sun Feb 15 10:33:47 2015 +0900
@@ -1,13 +1,14 @@
 \chapter{証明支援系言語 Agda による証明手法}
 \label{chapter:agda}
-第\ref{chapter:category}章においては functor, natural transformation, monad の定義と functional programming における対応について述べた。
+第\ref{chapter:category}章では functor, natural transformation, monad の定義を行ない、第\ref{chapter:functional_programming}章では functional programming における対応を述べた。
 その中で、 Functor 則や Monad 則といった満たすべき性質がいくつか存在した。
-functional programming において、あるデータ型やそれに対応する計算が Functor 則を満たすことを保証することは言語の実装に依存していい。
-例えば、 Haskell において functor は型クラスによって提供されるため、型レベルのチェックに留まっている。
-そのため、型チェックは通るが Functor 則を満たさない functor が定義可能となってしまう。
+functional programming において、あるデータ型と対応する計算が Functor 則を満たすかの保証は言語の実装に依存している。
+例えば、 Haskell において functor は型クラスによって提供されるため、型レベルのチェックを行なう。
+そのため、型チェックは通るが Functor 則を満たさない functor が定義できてしまう。
+よって Haskell において Delta Monad を定義しただけでは証明が存在しない。
+そこで証明支援系言語 Agda を用いて、 Delta が Functor 則と Monad 則を満たすことを証明する。
 
-そこで、証明支援系言語 Agda を用いて、 Delta が Functor 則と Monad 則を満たすことを証明することとする。
-そのためにまずは Agda における証明手法について述べる。
+第\ref{chapter:agda}章は Agda における証明手法について述べる。
 
 % {{{ Natural Deduction
 
--- a/proof_delta.tex	Fri Feb 13 18:10:07 2015 +0900
+++ b/proof_delta.tex	Sun Feb 15 10:33:47 2015 +0900
@@ -202,3 +202,99 @@
 
 \section{Delta が Monad 則を満たす証明}
 \label{section:delta_is_monad}
+\ref{section:monad_laws_in_agda}節において Agda における Monad則の定義を行なった。
+\ref{section:delta_is_monad}節では Delta に対する $ \eta $ と $ \mu $ の定義と Delta における $ triple $ がMonadであることの証明を行なう。
+これから証明する Delta を用いたプログラムは全ての値がバージョンを持ち、全ての関数はバージョンを持った値を返すものとする。
+さらに、バージョンはプログラム全体で1以上の値を持ち、プログラム内で統一されるものとする。
+
+まず、リスト\ref{src:delta_instance_monad} で示した Delta Monad のメタ計算を Agda で再定義する(リスト\ref{src:delta_monad_in_agda})。
+Haskell での定義は Kleisli Trple による定義であるため、リスト\ref{src:monad_and_bind}で示した Kleisli Triple と Monad の対応を用いて定義していることに留意する。
+
+\begin{table}[html]
+    \lstinputlisting[label=src:delta_monad_in_agda, caption=Agdaにおける Delta に対する Monad の定義] {src/delta_monad_in_agda.agda.replaced}
+\end{table}
+
+
+$ \eta $ に相当する delta-eta はメタ計算における T を1つ増やす演算に相当する。
+内包する値のバージョンに依存して Delta が持つバージョンが決まるため、 Nat の値によりバージョン数を決められるようにしておく。
+これは Delta でない値に対してはバージョン1とし、Deltaである値はDeltaのバージョンと同じバージョンを返すようにする。
+なお、パターンマッチの項に存在する \verb/{}/ は、 implicit な値のパターンマッチに用いられる。
+例えば \verb/{n = S x}/ とすれば、 implicit な値 n は S により構成され、残りの値は x に束縛される。
+
+次に $ \mu $ に相当する delta-mu を定義する。
+delta-mu は複数の \verb/TT -> T/に対応するメタ計算であるため、1段ネストされた Delta を受けとり、Deltaとして返す。
+これはバージョン管理された値に対し、バージョン管理された関数を適用した場合の値の選択に相当する。
+例えばバージョンが5であった場合、全ての組み合せは5パターン存在する。
+その中から5つを選ぶルールとして $ \mu $ を定義する。
+$ \mu $ は値と関数が同じバージョンであるような結果を選ぶように定義する。
+
+同じバージョンである値を選ぶため、先頭のバージョンの値を取る headDelta 関数と、先頭以外のバージョン列を取る tailDelta 関数を用いている。
+
+Delta Monad に対応する $ triple (T, \eta, \mu ) $ が定義できた。
+これから Monad 則を満たすことを証明していく。
+
+\begin{enumerate}
+    \item  $ \eta $ が natural transformation であること
+
+        まず、 $ \eta $ が natural transformation であることを示す(リスト\ref{src:delta_eta_is_nt_in_agda})。
+        eta は T を1つ増やす演算であるが、値のバージョンに応じて挙動を変える。
+        よって n によりパターンマッチすることで証明も変更する。
+        特に n が O である時は同じ項に簡約されるために refl で証明することができ、n が O 以上であれば再帰的に証明することができる。
+
+
+\begin{table}[html]
+    \lstinputlisting[label=src:delta_eta_is_nt_in_agda,
+                    caption= Agda における Delta の $ \eta$ が natural transformation である証明]
+                    {src/delta_eta_is_nt.agda.replaced}
+\end{table}
+    \item $ \mu $ が natural transformation であること
+
+        次に $ \mu $ が natural transformation であることを示す(リスト\ref{src:delta_mu_is_nt_in_agda})。
+
+        $ \mu $ の証明もバージョンによるパターンマッチで行なわれる。
+        バージョンが1である場合は refl で証明できるが、1以上の場合に同じ証明で再帰的に定義できない。
+        なぜなら、$ \mu $ はTT に対するであり、 TT の両方のバージョンが等しい場合にのみ適用する。
+        しかし証明中で外部のTに対する演算を先に行なっているために内部の項とバージョン数が合わない項が存在する。
+        その項に対する演算を含めた等式が証明中で必須となるため、別の項に証明を分離した。
+        分離した証明 \verb/tailDelta-to-tail-nt/ では \verb/d : Delta (Delta A (S (S m))) (S n) / のように内部と外部の Nat が違うことに留意してもらいたい。
+
+\begin{table}[html]
+    \lstinputlisting[basicstyle={\scriptsize},
+                     numberstyle={\tiny},
+                     label=src:delta_mu_is_nt_in_agda,
+                     caption= Agda における Delta の $ \mu$ が natural transformation である証明]
+                     {src/delta_mu_is_nt.agda.replaced}
+\end{table}
+
+    \item T に対する演算の単位元が存在する
+
+\begin{table}[html]
+    \lstinputlisting[basicstyle={\scriptsize},
+                     numberstyle={\tiny},
+                     label=src:delta_right_unity_law,
+                     caption= Agda における Delta に対する演算に右側単位元が存在する証明]
+                     {src/delta_right_unity_law.agda.replaced}
+\end{table}
+
+\begin{table}[html]
+    \lstinputlisting[basicstyle={\scriptsize},
+                     numberstyle={\tiny},
+                     label=src:delta_left_unity_law,
+                     caption= Agda における Delta に対する演算に左側単位元が存在する証明]
+                     {src/delta_left_unity_law.agda.replaced}
+\end{table}
+
+    \item T に対する演算の可換性が存在する
+
+\begin{table}[html]
+    \lstinputlisting[basicstyle={\scriptsize},
+                     numberstyle={\tiny},
+                     label=src:delta_association_law,
+                     caption= Agda における Delta に対する演算に可換性が存在する証明]
+                     {src/delta_association_law.agda.replaced}
+\end{table}
+
+\end{enumerate}
+
+
+
--- a/replace_agda.rb	Fri Feb 13 18:10:07 2015 +0900
+++ b/replace_agda.rb	Sun Feb 15 10:33:47 2015 +0900
@@ -1,6 +1,7 @@
 #!/usr/bin/env ruby
 
 replace_table = {
+  '->' => 'rightarrow',
   '∙'  => 'circ',
   '≡' => 'equiv',
   '×' => 'times',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/delta_association_law.agda	Sun Feb 15 10:33:47 2015 +0900
@@ -0,0 +1,39 @@
+delta-fmap-mu-to-tail : {l : Level} {A : Set l} (n m : Nat) ->
+    (d : Delta (Delta (Delta A (S (S m))) (S (S m))) (S n)) ->
+  delta-fmap tailDelta (delta-fmap delta-mu d)
+  ≡
+  (delta-fmap delta-mu (delta-fmap (delta-fmap tailDelta) (delta-fmap tailDelta d)))
+delta-fmap-mu-to-tail O O (mono (delta d ds)) = refl
+delta-fmap-mu-to-tail O (S n) (mono (delta (delta x (delta xx d)) (delta (delta dx (delta dxx dd)) ds))) = refl
+delta-fmap-mu-to-tail (S n) O (delta (delta (delta x (mono xx)) (mono (delta dx (mono dxx)))) ds) = begin
+  delta (mono dxx) (delta-fmap tailDelta (delta-fmap delta-mu ds))
+  ≡⟨ cong (\de -> delta (mono dxx) de) (delta-fmap-mu-to-tail n O ds) ⟩
+  delta (mono dxx)
+    (delta-fmap delta-mu
+     (delta-fmap (delta-fmap tailDelta) (delta-fmap tailDelta ds)))
+  ∎
+delta-fmap-mu-to-tail (S n) (S m) (delta (delta (delta x (delta xx d))
+                                                (delta (delta dx (delta dxx dd)) ds)) dds) = begin
+  delta (delta dxx (delta-mu (delta-fmap tailDelta (delta-fmap tailDelta ds))))
+    (delta-fmap tailDelta (delta-fmap delta-mu dds))
+  ≡⟨ cong (\de -> delta (delta dxx (delta-mu (delta-fmap tailDelta (delta-fmap tailDelta ds)))) de)
+           (delta-fmap-mu-to-tail n (S m) dds) ⟩
+  delta (delta dxx (delta-mu (delta-fmap tailDelta (delta-fmap tailDelta ds))))
+    (delta-fmap delta-mu (delta-fmap (delta-fmap tailDelta) (delta-fmap tailDelta dds)))
+  ∎
+
+
+
+delta-association-law : {l : Level} {A : Set l} {n : Nat} (d : Delta (Delta (Delta A (S n)) (S n)) (S n)) ->
+              ((delta-mu ∙ (delta-fmap delta-mu)) d) ≡ ((delta-mu ∙ delta-mu) d)
+delta-association-law {n =       O} (mono d)                          = refl
+delta-association-law {n = S n} (delta (delta (delta x d) dd) ds) = begin
+  delta x (delta-mu (delta-fmap tailDelta (delta-fmap delta-mu ds)))
+  ≡⟨ cong (\de -> delta x (delta-mu de)) (delta-fmap-mu-to-tail n n ds) ⟩
+  delta x (delta-mu (delta-fmap delta-mu (delta-fmap (delta-fmap tailDelta) (delta-fmap tailDelta ds))))
+  ≡⟨ cong (\de -> delta x de)
+           (delta-association-law (delta-fmap (delta-fmap tailDelta) (delta-fmap tailDelta ds))) ⟩
+  delta x (delta-mu (delta-mu (delta-fmap (delta-fmap tailDelta) (delta-fmap tailDelta ds))))
+  ≡⟨ cong (\de -> delta x (delta-mu de)) (delta-mu-is-nt tailDelta (delta-fmap tailDelta ds) ) ⟩
+  delta x (delta-mu (delta-fmap tailDelta (delta-mu (delta-fmap tailDelta ds))))
+  ∎
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/delta_eta_is_nt.agda	Sun Feb 15 10:33:47 2015 +0900
@@ -0,0 +1,12 @@
+delta-eta-is-nt : {l : Level} {A B : Set l} -> {n : Nat}
+      (f : A -> B) -> (x : A) ->
+      (delta-eta {n = n} ∙ f) x ≡ delta-fmap f (delta-eta x)
+delta-eta-is-nt {n = O}   f x = refl
+delta-eta-is-nt {n = S n} f x = begin
+  (delta-eta ∙ f) x                        ≡⟨ refl ⟩
+  delta-eta (f x)                          ≡⟨ refl ⟩
+  delta (f x) (delta-eta (f x))
+  ≡⟨ cong (\de -> delta (f x) de) (delta-eta-is-nt f x) ⟩
+  delta (f x) (delta-fmap f (delta-eta x)) ≡⟨ refl ⟩
+  delta-fmap f (delta x (delta-eta x))     ≡⟨ refl ⟩
+  delta-fmap f (delta-eta x)               ∎
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/delta_left_unity_law.agda	Sun Feb 15 10:33:47 2015 +0900
@@ -0,0 +1,15 @@
+delta-left-unity-law  : {l : Level} {A : Set l} {n : Nat} -> (d : Delta A (S n)) ->
+                                             (delta-mu  ∙ (delta-fmap delta-eta)) d ≡ id d
+delta-left-unity-law (mono x)    = refl
+delta-left-unity-law {n = (S n)} (delta x d) = begin
+  (delta-mu ∙ delta-fmap delta-eta) (delta x d)            ≡⟨ refl ⟩
+  delta-mu ( delta-fmap delta-eta (delta x d))             ≡⟨ refl ⟩
+  delta-mu (delta (delta-eta x) (delta-fmap delta-eta d))  ≡⟨ refl ⟩
+  delta (headDelta {n = S n} (delta-eta x)) (delta-mu (delta-fmap tailDelta (delta-fmap delta-eta d)))
+  ≡⟨ refl ⟩
+  delta x (delta-mu (delta-fmap tailDelta (delta-fmap delta-eta d)))
+  ≡⟨ cong (\de -> delta x (delta-mu de)) (sym (delta-covariant tailDelta delta-eta d)) ⟩
+  delta x (delta-mu (delta-fmap (tailDelta ∙ delta-eta {n = S n}) d))  ≡⟨ refl ⟩
+  delta x (delta-mu (delta-fmap (delta-eta {n = n}) d))  ≡⟨ cong (\de -> delta x de) (delta-left-unity-law d) ⟩
+  delta x d ≡⟨ refl ⟩
+  id (delta x d)  ∎
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/delta_monad_in_agda.agda	Sun Feb 15 10:33:47 2015 +0900
@@ -0,0 +1,17 @@
+headDelta : {l : Level} {A : Set l} {n : Nat} -> Delta A (S n) -> A
+headDelta (mono x)    = x
+headDelta (delta x _) = x
+
+tailDelta : {l : Level} {A : Set l} {n : Nat} ->
+    Delta A (S (S n)) -> Delta A (S n)
+tailDelta (delta _ d) = d
+
+
+delta-eta : {l : Level} {A : Set l} {n : Nat} -> A -> Delta A (S n)
+delta-eta {n = O}     x = mono x
+delta-eta {n = (S n)} x = delta x (delta-eta {n = n} x)
+
+delta-mu : {l : Level} {A : Set l} {n : Nat} ->
+           (Delta (Delta A (S n)) (S n)) -> Delta A (S n)
+delta-mu (mono x)    = x
+delta-mu (delta x d) = delta (headDelta x) (delta-mu (delta-fmap tailDelta d))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/delta_mu_is_nt.agda	Sun Feb 15 10:33:47 2015 +0900
@@ -0,0 +1,26 @@
+tailDelta-to-tail-nt : {l : Level} {A B : Set l} (n m  : Nat)
+                       (f : A -> B) (d : Delta (Delta A (S (S m))) (S n)) ->
+       delta-fmap tailDelta (delta-fmap (delta-fmap f) d) ≡ delta-fmap (delta-fmap f) (delta-fmap tailDelta d)
+tailDelta-to-tail-nt O O f (mono (delta x d)) = refl
+tailDelta-to-tail-nt O (S m) f (mono (delta x d)) = refl
+tailDelta-to-tail-nt (S n) O f (delta (delta x (mono xx)) d) = begin
+  delta (mono (f xx)) (delta-fmap tailDelta (delta-fmap (delta-fmap f) d))
+  ≡⟨ cong (\de -> delta (mono (f xx)) de) (tailDelta-to-tail-nt n O f d) ⟩
+  delta (mono (f xx)) (delta-fmap (delta-fmap f) (delta-fmap tailDelta d))
+  ∎
+tailDelta-to-tail-nt (S n) (S m) f (delta (delta x (delta xx d)) ds) = begin
+  delta (delta (f xx) (delta-fmap f d)) (delta-fmap tailDelta (delta-fmap (delta-fmap f) ds))
+  ≡⟨ cong (\de -> delta (delta (f xx) (delta-fmap f d)) de) (tailDelta-to-tail-nt n (S m) f ds) ⟩
+  delta (delta (f xx) (delta-fmap f d)) (delta-fmap (delta-fmap f) (delta-fmap tailDelta ds))
+  ∎
+
+delta-mu-is-nt : {l : Level} {A B : Set l} {n : Nat} -> (f : A -> B) -> (d : Delta (Delta A (S n)) (S n))
+               -> delta-mu (delta-fmap (delta-fmap f) d) ≡ delta-fmap f (delta-mu d)
+delta-mu-is-nt {n = O} f (mono d) = refl
+delta-mu-is-nt {n = S n} f (delta (delta x d) ds) = begin
+  delta (f x) (delta-mu (delta-fmap tailDelta (delta-fmap (delta-fmap f) ds)))
+  ≡⟨ cong (\de -> delta (f x) (delta-mu de)) (tailDelta-to-tail-nt n n f ds ) ⟩
+  delta (f x) (delta-mu (delta-fmap (delta-fmap f) (delta-fmap tailDelta ds)))
+  ≡⟨ cong (\de -> delta (f x) de) (delta-mu-is-nt f (delta-fmap tailDelta ds)) ⟩
+  delta (f x) (delta-fmap f (delta-mu (delta-fmap tailDelta ds)))
+  ∎
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/delta_right_unity_law.agda	Sun Feb 15 10:33:47 2015 +0900
@@ -0,0 +1,21 @@
+delta-right-unity-law : {l : Level} {A : Set l} {n : Nat} ->
+    (d : Delta A (S n)) -> (delta-mu ∙ delta-eta) d ≡ id d
+delta-right-unity-law (mono x)    = refl
+delta-right-unity-law (delta x d) = begin
+  (delta-mu ∙ delta-eta) (delta x d)
+  ≡⟨ refl ⟩
+  delta-mu (delta-eta (delta x d))
+  ≡⟨ refl ⟩
+  delta-mu (delta (delta x d) (delta-eta (delta x d)))
+  ≡⟨ refl ⟩
+  delta (headDelta (delta x d)) (delta-mu (delta-fmap tailDelta (delta-eta (delta x d))))
+  ≡⟨ refl ⟩
+  delta x (delta-mu (delta-fmap tailDelta (delta-eta (delta x d))))
+  ≡⟨ cong (\de -> delta x (delta-mu de)) (sym (delta-eta-is-nt  tailDelta (delta x d))) ⟩
+  delta x (delta-mu (delta-eta (tailDelta (delta x d))))
+  ≡⟨ refl ⟩
+  delta x (delta-mu (delta-eta d))
+  ≡⟨ cong (\de -> delta x de) (delta-right-unity-law d) ⟩
+  delta x d
+  ≡⟨ refl ⟩
+  id (delta x d)  ∎