Mercurial > hg > Papers > 2015 > atton-thesis
comparison paper/proof_delta.tex @ 60:1181b4facaf9
Move papers into directory
author | Yasutaka Higa <e115763@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 16 Feb 2015 17:09:53 +0900 |
parents | proof_delta.tex@5f0e13923cfd |
children | ce7701e4a308 |
comparison
equal
deleted
inserted
replaced
59:8d9c51dedde1 | 60:1181b4facaf9 |
---|---|
1 \chapter{Delta Monad が Monad である証明} | |
2 \label{chapter:proof_delta} | |
3 第\ref{chapter:agda}章では Agda における証明手法について述べた。 | |
4 第\ref{chapter:proof_delta}章では Agda を用いて Delta Monad が Monad であることを証明していく。 | |
5 証明のゴールは Delta Monad が Funcor 則と Monad 則を満たすことの証明である。 | |
6 なお、証明は全ての Delta が同じバージョンを持つという制約下において成り立った。 | |
7 | |
8 % {{{ Agda における Delta Monad の表現 | |
9 | |
10 \section{Agda における Delta Monad の表現} | |
11 \label{section:delta_in_agda} | |
12 \ref{section:delta_in_agda}節では Agda において Delta Monad を再定義する。 | |
13 Agda は Haskell において実装されているため、ほとんど同様に定義できる(リスト\ref{src:delta_in_agda})。 | |
14 | |
15 \begin{table}[html] | |
16 \lstinputlisting[label=src:delta_in_agda, caption=Agdaにおける Delta Monad のデータ定義] {src/delta.agda.replaced} | |
17 \end{table} | |
18 | |
19 data型 Delta は型A の値と Nat を持つ。 | |
20 | |
21 level とは型のlevelの区別に用いられるものである。 | |
22 Agda では型も値として扱えるため、同じ式において型と値が混同することがある。 | |
23 厳密に型と値を区別したい場合、level を定義することで区別する。 | |
24 levelは任意の level と、関数 suc により定義される。 | |
25 関数 suc は level を一つ上昇させる関数である。 | |
26 level l を適用した型を用いる時は Set l と記述する。 | |
27 今回は証明する対象のプログラムは Set l の level とし、それ以外は Set (suc l) の level とする。 | |
28 | |
29 Nat は自然数であり、プログラムのバージョンに対応する。 | |
30 自然数の定義は\ref{section:reasoning} 節にあるリスト \ref{src:nat}にならうものとする。 | |
31 | |
32 data 型 Delta は2つのコンストラクタにより構成される。 | |
33 | |
34 \begin{itemize} | |
35 \item mono | |
36 | |
37 プログラムの最初の変更単位を受けとり、バージョン1とする。 | |
38 型Aを取り、バージョンが1のDeltaを構成することでその表現とする。 | |
39 | |
40 \item delta | |
41 | |
42 変更単位と変更単位の列を受けとり、変更単位を追加する。 | |
43 これは変更によるバージョンアップに相当する。 | |
44 よって任意の1以上のバージョンを持つ Delta に変更単位を加えることでバージョンを1上昇させる。 | |
45 \end{itemize} | |
46 | |
47 Agda においてもデータ型 Delta が定義できた。 | |
48 これからこの定義を用いて Functor則と Monad 則を証明していく。 | |
49 | |
50 % }}} | |
51 | |
52 % {{{ Agda における Functor 則 | |
53 | |
54 \section{Agda における Functor 則} | |
55 \label{section:functor_in_agda} | |
56 Agda における Functor 則はリスト \ref{src:record_functor} のように記述した。 | |
57 | |
58 \begin{table}[html] | |
59 \lstinputlisting[label=src:record_functor, caption=Agdaにおける Functor則の定義] {src/record_functor.agda.replaced} | |
60 \end{table} | |
61 | |
62 Agda ではある性質を持つデータは record 構文によって記述する。 | |
63 record の値は record の定義時に要請した field を全て満たすことで構築される。 | |
64 よって、あるデータAが持つべき性質は field に定義し、A を用いた証明によって field を満たす。 | |
65 field を満たすことで record が構成できた場合、A がある性質を満たすことを Agda において証明したことになる。 | |
66 | |
67 record Functor は implicit な値 level と、型引数を持つ関数 F を持つ。 | |
68 record Functor が取る F は Set l を取り Set l を取る関数である。 | |
69 Set l が証明の対象となるプログラムであるため、関数F はプログラムのlevel で表現する。 | |
70 よって、プログラムの level l を取り、変更せずに level l の Set を返すようにする。 | |
71 それに対し、 F に対する証明となる record Functor は、証明の対象とするプログラムそのものではない。 | |
72 よって suc により level を一段上げる。 | |
73 これは、証明の対象となるプログラムと証明そのものを混同しないためである。 | |
74 | |
75 record Functor の field には以下のようなものがある。 | |
76 | |
77 \begin{itemize} | |
78 \item fmap | |
79 | |
80 Functor に要請される、category から category への map 関数である。 | |
81 型の定義はほとんど Haskell と同じである。 | |
82 fmap は任意の型に対して適用可能でなくてはいけないため、map する対象の型Aと map される対象の型Bは implicit とする。 | |
83 | |
84 \item preserve-id | |
85 | |
86 Functor則の id の保存である。 | |
87 型F A を持つ値x に対するfmap id と id の等価性がなくてはならない。 | |
88 | |
89 \item covariant | |
90 | |
91 Functor則における関数の合成の保存である。 | |
92 関数fとgを合成してから fmap により mapping しても、 f と g を個別に mapping してから合成しても等価性を持たなくてはならない。 | |
93 | |
94 \item fmap-equiv | |
95 | |
96 ある型A の値x に対して等価である関数f と g を考えた時、 型F A の値 fx の対し、 fmap f としても fmap gとしても等価であることを保証する。 | |
97 これは本来はFunctor則には存在しない。 | |
98 Agda において Monad の証明に必要であったために追加した。 | |
99 \end{itemize} | |
100 | |
101 % }}} | |
102 | |
103 % {{{ Delta が Functor 則を満たす証明 | |
104 | |
105 \section{Delta が Functor 則を満たす証明} | |
106 \label{section:delta_is_functor} | |
107 \ref{section:functor_in_agda}節では Agda における Functor則の表現について述べた。 | |
108 \ref{section:delta_is_functor}節では \ref{section:delta_in_agda}節の Delta Monad の定義を用いてFunctor則を証明していく。 | |
109 | |
110 まず、Agdaにおける delta に対する fmap の定義を示す(リスト\ref{src:delta_fmap_in_agda})。 | |
111 | |
112 \begin{table}[html] | |
113 \lstinputlisting[label=src:delta_fmap_in_agda, caption= Agda における Delta に対する fmap の定義] {src/delta_fmap.agda} | |
114 \end{table} | |
115 | |
116 バージョンが1以上の Delta について fmap を定義する。 | |
117 関数 f は型 A から B への関数とし、 Delta A から Delta B への関数に mapping する。 | |
118 コンストラクタ2つのパターンマッチを使って再帰的に f を delta の内部の値への適応することで fmap を行なう。 | |
119 | |
120 データ型Delta と関数fmap を定義できたので、これらが Functor 則を満たすか証明していく。 | |
121 なお、今回 Delta は全ての場合においてバージョンを1以上持つものとする。 | |
122 その制約は引数の Delta のバージョンに必ず S を付けることで1以下の値を受けつけないようにすることで行なう。 | |
123 | |
124 | |
125 \begin{itemize} | |
126 \item fmap は id を保存する | |
127 | |
128 リスト\ref{src:delta_preserve_id}に証明を示す。 | |
129 | |
130 \begin{table}[html] | |
131 \lstinputlisting[label=src:delta_preserve_id, caption= Delta における fmap も id を保存する証明] {src/delta_preserve_id.agda.replaced} | |
132 \end{table} | |
133 | |
134 | |
135 コンストラクタにようてパターン分けをする | |
136 mono の場合はfmapの定義により同じ項に変形されるために relf で証明できる。 | |
137 delta の場合、delta の 第一引数は mono の時のように同じ項に変形できる。 | |
138 しかし第二引数は fmap の定義により \verb/delta-fmap d id/ に変形される。 | |
139 見掛け上は等式の左辺と変わらないように見えるが、先頭1つめを除いているため、引数で受けたバージョンよりも1つだけ値が下がっている。 | |
140 よって最終的にバージョン1である mono になるまで再帰的に delta-preserve-id 関数を用いて変形した後に cong によって先頭1つめを適用し続けることで証明ができる。 | |
141 | |
142 \item fmap は関数の合成を保存する | |
143 | |
144 リスト\ref{src:delta_covariant}に証明を示す。 | |
145 | |
146 \begin{table}[html] | |
147 \lstinputlisting[label=src:delta_covariant, caption= Delta における fmap も関数の合成を保存する証明] {src/delta_covariant.agda.replaced} | |
148 \end{table} | |
149 | |
150 id の保存のように、コンストラクタによるパターンマッチを行なう。 | |
151 バージョンが1の場合は同じものに簡約され、1より大きい場合は再帰的に変形することで証明できる。 | |
152 \end{itemize} | |
153 | |
154 Delta と fmap と2つの証明を用いて Functor record を構成する(リスト\ref{src:delta_is_functor})。 | |
155 | |
156 | |
157 \begin{table}[html] | |
158 \lstinputlisting[label=src:delta_is_functor, caption= Delta が Functor則を満たすことの証明] {src/delta_is_functor.agda.replaced} | |
159 \end{table} | |
160 | |
161 record が正しく構成できたため、Delta は Functor 則を満たす。 | |
162 Agda ではこのように法則とデータの関連付けを行なう。 | |
163 | |
164 % }}} | |
165 | |
166 % {{{ Agda における Monad 則 | |
167 | |
168 \section{Agda における Monad 則} | |
169 \label{section:monad_laws_in_agda} | |
170 \ref{section:functor_in_agda}節と\ref{section:delta_is_functor}節では Delta が Functor 則を満たすことの証明を行なった。 | |
171 \ref{section:monad_laws_in_agda}節では同じように Monad 則の定義を行ない、\ref{section:delta_is_monad}節で証明を行なう。 | |
172 | |
173 まずは Monad則の定義を行なう(リスト\ref{src:monad_laws_in_agda})。 | |
174 | |
175 \begin{table}[html] | |
176 \lstinputlisting[label=src:monad_laws_in_agda, caption= AgdaにおけるMonad則の定義] {src/monad_laws.agda.replaced} | |
177 \end{table} | |
178 | |
179 Monad 則とは $ triple(T, \eta, \mu) $ に対して課すべき制約であった。 | |
180 そのためまず要素として $ T $ , $ \eta $, $ \mu $ が存在する。 | |
181 T は Set l を取り Set l を返す型であり、Functor則を満たす。 | |
182 $ \eta $ は T を増やす関数であり、 $ \mu $ は T を減らす関数である。 | |
183 これら Monad の構成要素を定義する field である。 | |
184 | |
185 次に、$ \eta $ と $ \mu $ は natural transformation である必要がある。 | |
186 よって field に制約として $ \eta $ と $ \mu $ の natural transformation を定義する。 | |
187 なお、 field という予約語は複数書いても2つ目以降は無いものとして振る舞う。 | |
188 | |
189 ここで、 \verb/ fmap F / という項に注目して欲しい。 | |
190 値F は Functor T 型を持ち、fmap や2つの証明を内包する。 | |
191 fmap や証明へのアクセスは \verb/ field-name record-value / と記述する。 | |
192 例えば、リスト\ref{src:delta_is_functor}で定義した Functor Delta の型を持つ値 \verb/delta-is-functor/ に対して \verb/ fmap delta-is-functor/ とすると関数 delta-fmap が得られる。 | |
193 つまり、\verb/fmap F f/ とするのは Functor則が証明された F の fmap に関数fを適用することとなる。 | |
194 | |
195 最後に $ triple (T, \eta, \mu) $ に対する Monad 則に相当する等式を記述する。 | |
196 Monad則は可換図として与えられたTに対する演算の可換性と、Tに対する演算の単位元を強制するものであった。 | |
197 Tに対する演算の可換性は association-law として、単位元の強制は unity-law として記述できる。 | |
198 unity-law はTに対する演算が右側と左側の二種類があるため、 right-unity-law と left-unity-law に分割した。 | |
199 | |
200 これら全ての field を満たすような証明を記述できれば、 $ triple (T, \eta, \mu) $ は Monad であると言える。 | |
201 | |
202 % }}} | |
203 | |
204 % {{{ Delta が Monad 則を満たす証明 | |
205 | |
206 \section{Delta が Monad 則を満たす証明} | |
207 \label{section:delta_is_monad} | |
208 \ref{section:monad_laws_in_agda}節において Agda における Monad則の定義を行なった。 | |
209 \ref{section:delta_is_monad}節では Delta に対する $ \eta $ と $ \mu $ の定義と Delta における $ triple $ がMonadであることの証明を行なう。 | |
210 これから証明する Delta を用いたプログラムは全ての値がバージョンを持ち、全ての関数はバージョンを持った値を返すものとする。 | |
211 さらに、バージョンはプログラム全体で1以上の値を持ち、プログラム内で統一されるものとする。 | |
212 | |
213 まず、リスト\ref{src:delta_instance_monad} で示した Delta Monad のメタ計算を Agda で再定義する(リスト\ref{src:delta_monad_in_agda})。 | |
214 Haskell での定義は Kleisli Trple による定義であるため、リスト\ref{src:monad_and_bind}で示した Kleisli Triple と Monad の対応を用いて定義していることに留意する。 | |
215 | |
216 \begin{table}[html] | |
217 \lstinputlisting[label=src:delta_monad_in_agda, caption=Agdaにおける Delta に対する Monad の定義] {src/delta_monad_in_agda.agda.replaced} | |
218 \end{table} | |
219 | |
220 | |
221 $ \eta $ に相当する delta-eta はメタ計算における T を1つ増やす演算に相当する。 | |
222 内包する値のバージョンに依存して Delta が持つバージョンが決まるため、 Nat の値によりバージョン数を決められるようにしておく。 | |
223 なお、パターンマッチの項に存在する \verb/{}/ は、 implicit な値のパターンマッチに用いられる。 | |
224 例えば \verb/{n = S x}/ とすれば、 implicit な値 n は S により構成される時にこの定義が実行され、S を省いた残りの値は x に束縛される。 | |
225 | |
226 次に $ \mu $ に相当する delta-mu を定義する。 | |
227 delta-mu は複数の \verb/TT -> T/に対応するメタ計算であるため、1段ネストされた Delta を受けとり、Deltaとして返す。 | |
228 これはバージョン管理された値に対し、バージョン管理された関数を適用した場合の値の選択に相当する。 | |
229 例えばバージョンが5であった場合、全ての組み合せは5パターン存在する。 | |
230 その中から5つを選ぶルールとして $ \mu $ を定義する。 | |
231 $ \mu $ は値と関数が同じバージョンであるような計算結果を選ぶように定義する。 | |
232 | |
233 同じバージョンである値を選ぶため、先頭のバージョンの値を取る headDelta 関数と、先頭以外のバージョン列を取る tailDelta 関数を用いている。 | |
234 | |
235 Delta Monad に対応する $ triple (T, \eta, \mu ) $ が定義できた。 | |
236 これから Monad 則を満たすことを証明していく。 | |
237 | |
238 \begin{enumerate} | |
239 \item $ \eta $ が natural transformation であること | |
240 | |
241 まず、 $ \eta $ が natural transformation であることを示す(リスト\ref{src:delta_eta_is_nt_in_agda})。 | |
242 eta は T を1つ増やす演算であるが、値のバージョンに応じて挙動を変える。 | |
243 よって n によりパターンマッチすることで証明も変更する。 | |
244 特に n が O である時は同じ項に簡約されるために refl で証明することができ、n が O 以上であれば再帰的に証明することができる。 | |
245 | |
246 | |
247 \lstinputlisting[label=src:delta_eta_is_nt_in_agda, | |
248 caption= Agda における Delta の $ \eta$ が natural transformation である証明] | |
249 {src/delta_eta_is_nt.agda.replaced} | |
250 \item $ \mu $ が natural transformation であること | |
251 | |
252 次に $ \mu $ が natural transformation であることを示す(リスト\ref{src:delta_mu_is_nt_in_agda})。 | |
253 | |
254 $ \mu $ の証明もバージョンによるパターンマッチで行なわれる。 | |
255 バージョンが1である場合は refl で証明できるが、1以上の場合に同じ証明で再帰的に定義できない。 | |
256 なぜなら、$ \mu $ はTT に対するであり、 TT の両方のバージョンが等しい場合にのみ適用する。 | |
257 しかし証明中で外部のTに対する演算を先に行なっているために内部の項とバージョン数が合わない項が存在する。 | |
258 その項に対する演算を含めた等式が証明中で必須となるため、別の項に証明を分離した。 | |
259 分離した証明 \verb/tailDelta-to-tail-nt/ では \verb/d : Delta (Delta A (S (S m))) (S n) / のように内部と外部の Nat が違うことに留意してもらいたい。 | |
260 | |
261 \begin{table}[html] | |
262 \lstinputlisting[basicstyle={\scriptsize}, | |
263 numberstyle={\tiny}, | |
264 label=src:delta_mu_is_nt_in_agda, | |
265 caption= Agda における Delta の $ \mu$ が natural transformation である証明] | |
266 {src/delta_mu_is_nt.agda.replaced} | |
267 \end{table} | |
268 | |
269 \newpage | |
270 | |
271 \item T に対する演算の単位元が存在する | |
272 | |
273 図\ref{fig:monad_laws}で示した右側の可換図に相当する。 | |
274 単位元に相当する演算は右側と左側の2つが存在するため、証明も2つに分割する。 | |
275 | |
276 右側単位元の証明をリスト\ref{src:delta_right_unity_law}に示す。 | |
277 | |
278 \lstinputlisting[basicstyle={\scriptsize}, | |
279 numberstyle={\tiny}, | |
280 label=src:delta_right_unity_law, | |
281 caption= Agda における Delta に対する演算に右側単位元が存在する証明] | |
282 {src/delta_right_unity_law.agda.replaced} | |
283 | |
284 バージョンが1である時は同じ項となるため refl となる。 | |
285 バージョンが1以上である時は再帰的に定義することになるが、途中で $ \eta $ が natural transformation である性質を利用している。 | |
286 | |
287 次に左側単位元の証明をリスト\ref{src:delta_left_unity_law}に示す。 | |
288 | |
289 \begin{table}[html] | |
290 \lstinputlisting[basicstyle={\scriptsize}, | |
291 numberstyle={\tiny}, | |
292 label=src:delta_left_unity_law, | |
293 caption= Agda における Delta に対する演算に左側単位元が存在する証明] | |
294 {src/delta_left_unity_law.agda.replaced} | |
295 \end{table} | |
296 | |
297 これまでの証明と同様にバージョンが1である場合は定義から同じ項となる。 | |
298 バージョンが1以上の場合、Functor則の関数の合成の保存を利用して証明を再帰的に行なう。 | |
299 | |
300 \item T に対する演算の可換性が存在する | |
301 | |
302 図\ref{fig:monad_laws}で示した左側の可換図に相当する。 | |
303 演算の可換性の証明をリスト\ref{src:delta_association_law}に示す。 | |
304 | |
305 \begin{table}[html] | |
306 \lstinputlisting[basicstyle={\scriptsize}, | |
307 numberstyle={\tiny}, | |
308 label=src:delta_association_law, | |
309 caption= Agda における Delta に対する演算に可換性が存在する証明] | |
310 {src/delta_association_law.agda.replaced} | |
311 \end{table} | |
312 | |
313 $ \mu $ を用いて TTT から T にする際に、右側2つのTに対して先に $ \mu $ を用いるか、左側2つから先に用いるかの可換性である。 | |
314 よって \verb/Delta (Delta (Delta A))/から \verb/Delta A/ とする演算の等式となる。 | |
315 | |
316 バージョンが1である場合はやはり同じ項に簡約される。 | |
317 しかしバージョンが1以上である場合は複雑な式変形を行なう。 | |
318 | |
319 パターンマッチにより最も外側の Delta は分解されるため、バージョンが1下がる。 | |
320 しかし内側の Delta 2つはバージョンが異なるため、外側2つの Delta のバージョンが異なってしまい $ \mu $ が適用できない。 | |
321 よって \verb/delta-fmap-mu-to-tail/ として部分的な等式を証明してから可換性を証明する。 | |
322 \verb/delta-fmap-mu-to-tail/ では Delta のバージョンが \verb/Delta (Delta (Delta A (S (S m))) (S (S m))) (S n)/ となっていることに注目してもらいたい。 | |
323 | |
324 \verb/delta-fmap-mu-to-tail/ に加え、 $ \mu $ が natural transformation であることを利用して再帰的に定義することで証明ができる。 | |
325 | |
326 \end{enumerate} | |
327 | |
328 | |
329 Delta Monad の定義と、5つの証明を用いて Moand の record が構築できることを確認する(リスト\ref{src:delta_is_monad})。 | |
330 | |
331 \begin{table}[html] | |
332 \lstinputlisting[label=src:delta_is_monad, caption= Agda における Delta が Monad 則を満たす証明] {src/delta_is_monad.agda.replaced} | |
333 \end{table} | |
334 | |
335 全ての Delta が同じバージョンを持つ時、 $ triple(T, \eta, \mu) $ は Monad則を満たすことを示せた。 | |
336 | |
337 % }}} | |
338 |