<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-30049755</id><updated>2012-01-19T16:54:20.478+09:00</updated><category term='RWH'/><category term='Joke'/><category term='Why3'/><category term='scala'/><category term='Maude'/><category term='translation'/><category term='チュートリアル'/><category term='7-Lang'/><category term='Coq'/><category term='separation logic'/><category term='FM'/><category term='tutorial'/><category term='Misc'/><category term='TAPL'/><category term='MathJax'/><category term='OCaml'/><category term='翻訳'/><category term='Blogger'/><category term='Java'/><category term='Haskell'/><category term='Agda'/><category term='FoCaLize'/><category term='Ruby'/><category term='Web Flavor'/><category term='PFDS'/><category term='Memo'/><category term='Alloy'/><category term='Link'/><category term='LaTeX'/><category term='Event'/><category term='OmegaT'/><category term='Project euler'/><title type='text'>Functional Programming Memo</title><subtitle type='html'>Personal memorandum for studying functional languages, theorem proving, and formal verification.  But other topics might be included.  Written in Japanese (Shift-JIS Encoding).</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default?start-index=101&amp;max-results=100'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>171</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-30049755.post-3681491718292533480</id><published>2012-01-19T16:53:00.002+09:00</published><updated>2012-01-19T16:54:20.484+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Event'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Tutorial on 1/12, 2/2, 2/9, and 2/16</title><content type='html'>&lt;a href="http://www.infoq.com/jp/articles/coqtutorial"&gt;イベントレポート：「Coqチュートリアル#1」 @ InfoQ&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;今回、豆蔵様より会場を提供していただけることになって、前々から計画していた平日夜の複数回開催のCoqチュートリアルを 1/12, 2/2, 2/9, 2/16 という予定で開催します。&lt;br /&gt;参加申し込みについては上記リンクから辿って頂ければと思います。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3681491718292533480?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3681491718292533480/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3681491718292533480' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3681491718292533480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3681491718292533480'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2012/01/coq-coq-tutorial-on-112-22-29-and-216.html' title='[Coq] Coq Tutorial on 1/12, 2/2, 2/9, and 2/16'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5384687670323614606</id><published>2012-01-05T22:40:00.002+09:00</published><updated>2012-01-05T22:40:47.766+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] itoa in Coq</title><content type='html'>https://github.com/tmiya/coq/blob/master/Radix/Radix.v&lt;br /&gt;&lt;br /&gt;自然数$n$を$p \ge 2$で割って余りを求め、商をまた割って、と繰り返すことで$n$の$p$進表示を得られますが、そのencode/decodeをCoqで書きました。勿論、encodeとdecodeが逆関数になっていることも証明済みです。&lt;br /&gt;encode関数を使って、C言語にあるitoa関数を書きました。これがあれば、数字を文字列に変換出来ますからFizzBuzzもCoqで書けます。&lt;br /&gt;そのうちCoq user contributionに登録しよう。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5384687670323614606?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5384687670323614606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5384687670323614606' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5384687670323614606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5384687670323614606'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2012/01/coq-itoa-in-coq.html' title='[Coq] itoa in Coq'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-1153421977646502612</id><published>2011-12-31T21:09:00.004+09:00</published><updated>2011-12-31T21:09:49.477+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>[Misc] 2011 Summary</title><content type='html'>2011年を振り返ってですが、&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;今年も&lt;a href="http://groups.google.com/group/fm-forum"&gt;Formal Methods Forum&lt;/a&gt;が続けられた。@kencoba さん他皆様のお陰だと思います。来年も継続して行きたい。&lt;/li&gt;&lt;li&gt;&lt;a href="http://coq.inria.fr/pylons/contribs/view/RegExp/v8.3"&gt;RegExpライブラリ&lt;/a&gt;が書けたのは嬉しかった。2012年も上半期に何か纏まった成果を出したいなぁ。&lt;/li&gt;&lt;li&gt;数学関係の読書会に参加した。@bonotake さん、@cocoatomo さん、@erutuf13 さんのおかげです。ありがとうございます。学部時代は20年ぐらい前のはずだが、昔勉強した数学、案外忘れてないものだなー。2012年はとりあえず群環体の入門書を終わらせ、2013年以降に繋げたいな。&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.icfpconference.org/icfp2011/"&gt;ICFP 2011&lt;/a&gt;は、聞いた話の全部が理解出来た訳じゃないけど楽しかったー。年休とって参加した甲斐がありました。途中体調崩したのは残念というか、適宜中休み入れないと駄目か。今後も年休取れるなら学会聞きに行きたいな。&lt;/li&gt;&lt;li&gt;名古屋の&lt;a href="http://coq.g.hatena.ne.jp/yoshihiro503/20100331/p1"&gt;Proof Cafe&lt;/a&gt;の皆様のご協力を得て、&lt;a href="http://partake.in/events/ac41261d-6026-4d09-8814-5ad3e58446e8"&gt;Proof Summit 2011&lt;/a&gt;を開催出来ました。時間調整にかなり失敗して発表者の皆様にはかなり迷惑をおかけしましたが、結果としては充実したイベントになったかなー。&lt;/li&gt;&lt;li&gt;&lt;a href="http://staff.aist.go.jp/reynald.affeldt/tpp2011/"&gt;TPP 2011&lt;/a&gt;を聞きに行きました。これも勉強になり楽しかったです。来年(千葉大で開催らしい)とか、何か発表出来るといいなぁ。&lt;/li&gt;&lt;/ul&gt;来年も宜しくお願いします＞皆様。&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1153421977646502612?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/1153421977646502612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=1153421977646502612' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1153421977646502612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1153421977646502612'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/12/misc-2011-summary.html' title='[Misc] 2011 Summary'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-4501788810672628835</id><published>2011-12-30T15:25:00.002+09:00</published><updated>2011-12-30T16:05:40.034+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Group defined by one operation</title><content type='html'>通常、群$G$を定義するときは、演算 $\cdot : (G&amp;nbsp;\times G)&amp;nbsp;\rightarrow G$, と単位元 $e:G$, 逆元 $(\cdot)^{-1}:G \rightarrow G$ から定義しますが、$x/y := xy^{-1}$ を基本的な定義として群を定義することも出来ます。（$H&amp;nbsp;\subset G$ が部分群であることを示すには $\forall x,¥; y&amp;nbsp;\in H,\;\; x/y&amp;nbsp;\in H$ を示せば良い、など計算の手間が減って都合が良い。）&lt;br /&gt;&lt;br /&gt;演算 $x/y : (G&amp;nbsp;\times G)&amp;nbsp;\ni (x,y)&amp;nbsp;\mapsto xy^{-1}&amp;nbsp;\in G$ が下記の公理を満たすならば、&lt;br /&gt;&lt;ul&gt;&lt;li&gt;$a/a = b/b$&lt;/li&gt;&lt;li&gt;$a/(b/b) = a$&lt;/li&gt;&lt;li&gt;$(a/a)/(b/c) = c/b$&lt;/li&gt;&lt;li&gt;$(a/c)/(b/c) = a/b$&lt;/li&gt;&lt;/ul&gt;$G$ は群になります。というのを Coq で証明しました。コードは&amp;nbsp;&lt;a href="https://github.com/tmiya/coq/blob/master/group/group2.v"&gt;https://github.com/tmiya/coq/blob/master/group/group2.v&lt;/a&gt;&amp;nbsp;にも置いてあります。&lt;br /&gt;群の法則の中では、結合則を示すのに苦労しました。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(** Group defined by one operation *)&lt;br /&gt;(* Operator 'x/y' means xy^{-1}.&lt;br /&gt;  Probe that '/' and four axioms obout it defines a group. *)&lt;br /&gt;&lt;br /&gt;Section Group2.&lt;br /&gt;Parameter G:Set.&lt;br /&gt;(* G is not an empty set. At least one element exists. *)&lt;br /&gt;Parameter g0:G. &lt;br /&gt;Parameter op:G-&amp;gt;G-&amp;gt;G.&lt;br /&gt;Notation "a / b" := (op a b).&lt;br /&gt;(* Axioms for / *)&lt;br /&gt;Parameter G1: forall a b, a/a = b/b.&lt;br /&gt;Parameter G2: forall a b, a/(b/b) = a.&lt;br /&gt;Parameter G3: forall a b c, (a/a)/(b/c) = c/b.&lt;br /&gt;Parameter G4: forall a b c, (a/c)/(b/c) = a/b.&lt;br /&gt;&lt;br /&gt;Definition e:G := g0/g0.&lt;br /&gt;Notation "1" := e.&lt;br /&gt;Definition mult(a b:G) := (a/(1/b)).&lt;br /&gt;Notation "a * b" := (mult a b).&lt;br /&gt;&lt;br /&gt;Lemma op_refl_1 : forall a, a/a = 1.&lt;br /&gt;Proof.&lt;br /&gt;intro a. unfold "1". eapply G1.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma op_1 : forall a, a/1 = a.&lt;br /&gt;Proof.&lt;br /&gt;intro. unfold "1". rewrite G2. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Theorem left_id : forall a, 1*a = a.&lt;br /&gt;Proof.&lt;br /&gt;intro. unfold "1". unfold "*".&lt;br /&gt;erewrite G3. eapply op_1.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Theorem right_id : forall a, a*1 = a.&lt;br /&gt;Proof.&lt;br /&gt;intro. unfold "*". erewrite op_1.&lt;br /&gt;erewrite op_1. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Definition inv(a:G) := (1/a).&lt;br /&gt;Notation "! a" := (inv a) (at level 91).&lt;br /&gt;&lt;br /&gt;Theorem left_inv : forall a, (!a)*a=1.&lt;br /&gt;Proof.&lt;br /&gt;intros. unfold "!". unfold "*".&lt;br /&gt;rewrite G4. erewrite op_1. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma inv_inv : forall a, 1/(1/a) = a.&lt;br /&gt;Proof.&lt;br /&gt;intros.&lt;br /&gt;replace (1/(1/a)) with (1/1/(1/a)).&lt;br /&gt; rewrite G3. eapply op_1.&lt;br /&gt;erewrite op_1. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Theorem right_inv : forall a, a*(!a)=1.&lt;br /&gt;Proof.&lt;br /&gt;intros. unfold "!". unfold "*".&lt;br /&gt;erewrite inv_inv. eapply op_refl_1.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma inv_op : forall a b, inv (a/b) = b/a.&lt;br /&gt;Proof.&lt;br /&gt;intros. unfold "!". unfold "1".&lt;br /&gt;erewrite G3. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma inv_idem : forall a, inv (inv a) = a.&lt;br /&gt;Proof.&lt;br /&gt;intros. unfold "!". eapply inv_inv.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma op_eq : forall a b c d,&lt;br /&gt; a/b = c/d -&amp;gt; b/a = d/c.&lt;br /&gt;Proof.&lt;br /&gt;intros.&lt;br /&gt;replace (b/a) with (1/1/(a/b)).&lt;br /&gt; replace (d/c) with (1/1/(c/d)).&lt;br /&gt;  rewrite H. auto.&lt;br /&gt; erewrite G3. auto.&lt;br /&gt;erewrite G3. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma op_mult : forall a b, (a/b)*b = a.&lt;br /&gt;Proof.&lt;br /&gt;intros. unfold "*". erewrite G4.&lt;br /&gt;eapply op_1.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma rm_op_2 : forall a b c, a/c=b/c -&amp;gt; a=b.&lt;br /&gt;Proof.&lt;br /&gt;intros. assert(a/c*c = b/c*c).&lt;br /&gt; rewrite H. auto.&lt;br /&gt;erewrite op_mult in H0.&lt;br /&gt;erewrite op_mult in H0. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma rm_op_1 : forall a b c, a/b=a/c -&amp;gt; b=c.&lt;br /&gt;Proof.&lt;br /&gt;intros. specialize(op_eq a b a c H). intro.&lt;br /&gt;eapply (rm_op_2 b c a H0).&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma mult_op : forall a b, (a*b)/b = a.&lt;br /&gt;Proof.&lt;br /&gt;intros. unfold "*".&lt;br /&gt;replace (a/(1/b)/b) with (a/(1/b)/(1/(1/b))).&lt;br /&gt;rewrite G4. rewrite op_1. auto.&lt;br /&gt;replace (1/(1/b)) with b. auto.&lt;br /&gt;erewrite inv_inv. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma assoc_2 : forall a b c, a/(b/c) = a*c/b.&lt;br /&gt;intros.&lt;br /&gt;replace (a/(b/c)) with ((a*c)/c/(b/c)).&lt;br /&gt;rewrite G4. auto.&lt;br /&gt;rewrite mult_op. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma assoc_3 : forall a b c, a*(c/b) = a*c/b.&lt;br /&gt;intros. &lt;br /&gt;replace (a*(c/b)) with (a/(inv (c/b))).&lt;br /&gt;unfold "!". replace (1/(c/b)) with (b/c).&lt;br /&gt;rewrite assoc_2. auto.&lt;br /&gt;replace (1/(c/b)) with (1/1/(c/b)).&lt;br /&gt;rewrite G3. auto. rewrite op_1. auto.&lt;br /&gt;unfold inv. unfold "*". auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma assoc_4 : forall a b c, a*(c*(inv b)) = a*c*(inv b).&lt;br /&gt;intros. unfold inv.&lt;br /&gt;replace (c*(1/b)) with (c/b).&lt;br /&gt;replace (a*c*(1/b)) with (a*c/b).&lt;br /&gt;eapply assoc_3.&lt;br /&gt;unfold "*". rewrite inv_inv. auto.&lt;br /&gt;unfold "*". rewrite inv_inv. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Theorem assoc : forall a b c, a*(b*c) = a*b*c.&lt;br /&gt;intros.&lt;br /&gt;replace c with (inv (inv c)).&lt;br /&gt;eapply assoc_4.&lt;br /&gt;eapply inv_idem.&lt;br /&gt;Qed.&lt;br /&gt;End Group2.&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-4501788810672628835?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/4501788810672628835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=4501788810672628835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4501788810672628835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4501788810672628835'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/12/coq-group-defined-by-one-operation.html' title='[Coq] Group defined by one operation'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-9105494432647884943</id><published>2011-12-16T07:06:00.000+09:00</published><updated>2011-12-19T13:32:24.204+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Why3'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Why3] How to Use Why3 (Theorem Prover Advent Calender)</title><content type='html'>この記事は&lt;a href="http://partake.in/events/30381166-394a-4fab-a5ea-5984d051de01"&gt;Theorem Proving Advent Calendar 2011&lt;/a&gt;の16日目の記事です。（なお、Advent Calender の参加者も継続募集中です。）&lt;br /&gt;&lt;br /&gt;&lt;a href="http://study-func-prog.blogspot.com/2011/12/why3-install-of-why3-tool-theorem.html"&gt;前回&lt;/a&gt;はWhy3のインストールと動作確認を行いましたが、今回はWhy3 を使ったプログラミング検証について解説します。&lt;br /&gt;&lt;br /&gt;素で Coq を使って手続き型的なコード(変数への破壊的代入を用いたコード)を証明する際には、Coq内DSLとして手続き的言語を実装して、Hoareトリプルを用いて言語の公理的意味論を実装して、参照や配列に関する公理ライブラリを準備して云々、という手間が必要になります。（PierceのSoftware Foundationsに&lt;a href="http://www.cis.upenn.edu/%7Ebcpierce/sf/Imp.html"&gt;Imp:Simple Imperative Programs&lt;/a&gt;という章があります。あるいは当Advent Calenderのimunolionさんによる２日目の記事、&lt;a href="http://d.hatena.ne.jp/imunolion/20111201/1322749907"&gt;Coqでセンター試験のBasicを解く&lt;/a&gt;、を参照下さい。）&lt;br /&gt;&lt;br /&gt;Why3 を用いることで、上記の手間を省くことが出来ます。(そして運が良ければ自動証明で片が付きます。)&lt;br /&gt;Why3 では、Why3ML というML系言語でプログラムを実装出来ます。その際に、コード中にアノテーションとしてHoareの事前事後条件、ループ不変条件などを記述します。Why3 は参照を用いた破壊的代入や for-loop などの手続き言語的な構文をサポートします。そして事前事後条件やループ不変条件から weakest precondition を計算してくれ、証明課題を生成します。&lt;br /&gt;&lt;br /&gt;マニュアルのプログラム例は VSTTE 2010 の課題から取られているようで、その最初の問題を Why3 で解いてみます。 課題は&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;自然数 $N$ 個を格納した配列の要素の最大値 $\mathrm{max}$, 要素の和 $\mathrm{sum}$ について $\mathrm{sum} \le N \times \mathrm{max}$&lt;/blockquote&gt;が成り立つことを示せ、というものです。&lt;br /&gt;&lt;br /&gt;■Why3ML でのプログラミング&lt;br /&gt;&lt;br /&gt;上の問題を Why3ML 言語で実装したものです。まぁ大体読めますよね。&lt;br /&gt;ref を使うことで参照を作れます。!でderefでき、:= で再代入です。refはWhy3のライブラリとして定義されているので、興味のある人は modules/ref.mlw を読むと良いでしょう。a[i] のように配列の値を参照出来ますが、array も同様に array.mlw で定義されています。&lt;br /&gt;{...} は事前事後条件、invariant {...} はループ不変条件です。事後条件の部分に課題が書かれています。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;% cat max_sum.mlw &lt;br /&gt;module MaxAndSum&lt;br /&gt;&lt;br /&gt;  use import int.Int &lt;br /&gt;  use import module ref.Ref&lt;br /&gt;  use import module array.Array&lt;br /&gt;&lt;br /&gt;  let max_sum (a: array int) (n: int) =&lt;br /&gt;    { 0 &amp;lt;= n = length a /\ forall i:int. 0 &amp;lt;= i &amp;lt; n -&amp;gt; a[i] &amp;gt;= 0 }&lt;br /&gt;    let sum = ref 0 in&lt;br /&gt;    let max = ref 0 in&lt;br /&gt;    for i = 0 to n - 1 do&lt;br /&gt;      invariant { !sum &amp;lt;= i * !max }&lt;br /&gt;      if !max &amp;lt; a[i] then max := a[i];&lt;br /&gt;      sum := !sum + a[i]&lt;br /&gt;    done;&lt;br /&gt;    (!sum, !max)&lt;br /&gt;    { let (sum, max) = result in sum &amp;lt;= n * max }&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ここではforループが使用されていますが、Why3MLではloop-end, while-do-done, do-done などループ構文が複数用意されています。例外処理の構文はraiseで例外を投げて、try-with-endで例外を発生する箇所をガードする形。アサーションはassert, assume, check と同じようなものが３つ。パターンマッチ構文match-with-endもあります。構文の詳細はマニュアルを参照して下さい。&lt;br /&gt;&lt;br /&gt;■Alt-Ergoでの自動証明&lt;br /&gt;&lt;br /&gt;これをAlt-Ergoで自動証明してみます。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;% why3ml -P alt-ergo max_sum.mlw&lt;br /&gt;max_sum.mlw WP MaxAndSum WP_parameter max_sum : Unknown: Unknown (0.05s)&lt;br /&gt;%&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;が、Alt-Ergoは失敗しました。さすがに自動証明は通りませんでした。&lt;br /&gt;&lt;br /&gt;■Coq用の証明課題生成&lt;br /&gt;&lt;br /&gt;Coqの証明課題も生成してみます。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;% mkdir max_sum&lt;br /&gt;% why3ml -P coq -o max_sum max_sum.mlw&lt;br /&gt;% ls max_sum&lt;br /&gt;max_sum_MaxAndSum_WP_parameter_max_sum.v&lt;br /&gt;% cat max_sum/max_sum_MaxAndSum_WP_parameter_max_sum.v &lt;br /&gt;(* This file is generated by Why3's Coq driver *)&lt;br /&gt;(* Beware! Only edit allowed sections below    *)&lt;br /&gt;Require Import ZArith.&lt;br /&gt;Require Import Rbase.&lt;br /&gt;Definition unit  := unit.&lt;br /&gt;&lt;br /&gt;Parameter qtmark : Type.&lt;br /&gt;&lt;br /&gt;Parameter at1: forall (a:Type), a -&amp;gt; qtmark -&amp;gt; a.&lt;br /&gt;&lt;br /&gt;Implicit Arguments at1.&lt;br /&gt;&lt;br /&gt;Parameter old: forall (a:Type), a -&amp;gt; a.&lt;br /&gt;&lt;br /&gt;Implicit Arguments old.&lt;br /&gt;&lt;br /&gt;Inductive ref (a:Type) :=&lt;br /&gt;  | mk_ref : a -&amp;gt; ref a.&lt;br /&gt;Implicit Arguments mk_ref.&lt;br /&gt;&lt;br /&gt;Definition contents (a:Type)(u:(ref a)): a :=&lt;br /&gt;  match u with&lt;br /&gt;  | (mk_ref contents1) =&amp;gt; contents1&lt;br /&gt;  end.&lt;br /&gt;Implicit Arguments contents.&lt;br /&gt;&lt;br /&gt;Parameter map : forall (a:Type) (b:Type), Type.&lt;br /&gt;&lt;br /&gt;Parameter get: forall (a:Type) (b:Type), (map a b) -&amp;gt; a -&amp;gt; b.&lt;br /&gt;&lt;br /&gt;Implicit Arguments get.&lt;br /&gt;&lt;br /&gt;Parameter set: forall (a:Type) (b:Type), (map a b) -&amp;gt; a -&amp;gt; b -&amp;gt; (map a b).&lt;br /&gt;&lt;br /&gt;Implicit Arguments set.&lt;br /&gt;&lt;br /&gt;Axiom Select_eq : forall (a:Type) (b:Type), forall (m:(map a b)),&lt;br /&gt;  forall (a1:a) (a2:a), forall (b1:b), (a1 = a2) -&amp;gt; ((get (set m a1 b1)&lt;br /&gt;  a2) = b1).&lt;br /&gt;&lt;br /&gt;Axiom Select_neq : forall (a:Type) (b:Type), forall (m:(map a b)),&lt;br /&gt;  forall (a1:a) (a2:a), forall (b1:b), (~ (a1 = a2)) -&amp;gt; ((get (set m a1 b1)&lt;br /&gt;  a2) = (get m a2)).&lt;br /&gt;&lt;br /&gt;Parameter const: forall (b:Type) (a:Type), b -&amp;gt; (map a b).&lt;br /&gt;&lt;br /&gt;Set Contextual Implicit.&lt;br /&gt;Implicit Arguments const.&lt;br /&gt;Unset Contextual Implicit.&lt;br /&gt;&lt;br /&gt;Axiom Const : forall (b:Type) (a:Type), forall (b1:b) (a1:a), ((get (const(&lt;br /&gt;  b1):(map a b)) a1) = b1).&lt;br /&gt;&lt;br /&gt;Inductive array (a:Type) :=&lt;br /&gt;  | mk_array : Z -&amp;gt; (map Z a) -&amp;gt; array a.&lt;br /&gt;Implicit Arguments mk_array.&lt;br /&gt;&lt;br /&gt;Definition elts (a:Type)(u:(array a)): (map Z a) :=&lt;br /&gt;  match u with&lt;br /&gt;  | (mk_array _ elts1) =&amp;gt; elts1&lt;br /&gt;  end.&lt;br /&gt;Implicit Arguments elts.&lt;br /&gt;&lt;br /&gt;Definition length (a:Type)(u:(array a)): Z :=&lt;br /&gt;  match u with&lt;br /&gt;  | (mk_array length1 _) =&amp;gt; length1&lt;br /&gt;  end.&lt;br /&gt;Implicit Arguments length.&lt;br /&gt;&lt;br /&gt;Definition get1 (a:Type)(a1:(array a)) (i:Z): a := (get (elts a1) i).&lt;br /&gt;Implicit Arguments get1.&lt;br /&gt;&lt;br /&gt;Definition set1 (a:Type)(a1:(array a)) (i:Z) (v:a): (array a) :=&lt;br /&gt;  match a1 with&lt;br /&gt;  | (mk_array xcl0 _) =&amp;gt; (mk_array xcl0 (set (elts a1) i v))&lt;br /&gt;  end.&lt;br /&gt;Implicit Arguments set1.&lt;br /&gt;&lt;br /&gt;(* YOU MAY EDIT THE CONTEXT BELOW *)&lt;br /&gt;&lt;br /&gt;(* DO NOT EDIT BELOW *)&lt;br /&gt;&lt;br /&gt;Theorem WP_parameter_max_sum : forall (a:Z), forall (n:Z), forall (a1:(map Z&lt;br /&gt;  Z)), (((0%Z &amp;lt;= n)%Z /\ (n = a)) /\ forall (i:Z), ((0%Z &amp;lt;= i)%Z /\&lt;br /&gt;  (i &amp;lt;  n)%Z) -&amp;gt; (0%Z &amp;lt;= (get a1 i))%Z) -&amp;gt; ((((n - 1%Z)%Z &amp;lt;  0%Z)%Z -&amp;gt;&lt;br /&gt;  (0%Z &amp;lt;= (n * 0%Z)%Z)%Z) /\ ((0%Z &amp;lt;= (n - 1%Z)%Z)%Z -&amp;gt;&lt;br /&gt;  ((0%Z &amp;lt;= (0%Z * 0%Z)%Z)%Z /\ forall (max:Z), forall (sum:Z), (forall (i:Z),&lt;br /&gt;  ((0%Z &amp;lt;= i)%Z /\ (i &amp;lt;= (n - 1%Z)%Z)%Z) -&amp;gt; ((sum &amp;lt;= (i * max)%Z)%Z -&amp;gt;&lt;br /&gt;  (((0%Z &amp;lt;= i)%Z /\ (i &amp;lt;  a)%Z) /\ (((max &amp;lt;  (get a1 i))%Z -&amp;gt;&lt;br /&gt;  (((0%Z &amp;lt;= i)%Z /\ (i &amp;lt;  a)%Z) /\ forall (max1:Z), (max1 = (get a1 i)) -&amp;gt;&lt;br /&gt;  (((0%Z &amp;lt;= i)%Z /\ (i &amp;lt;  a)%Z) /\ forall (sum1:Z), (sum1 = (sum + (get a1&lt;br /&gt;  i))%Z) -&amp;gt; (sum1 &amp;lt;= ((i + 1%Z)%Z * max1)%Z)%Z))) /\ ((~ (max &amp;lt;  (get a1&lt;br /&gt;  i))%Z) -&amp;gt; (((0%Z &amp;lt;= i)%Z /\ (i &amp;lt;  a)%Z) /\ forall (sum1:Z),&lt;br /&gt;  (sum1 = (sum + (get a1 i))%Z) -&amp;gt; (sum1 &amp;lt;= ((i + 1%Z)%Z * max)%Z)%Z)))))) /\&lt;br /&gt;  ((sum &amp;lt;= (((n - 1%Z)%Z + 1%Z)%Z * max)%Z)%Z -&amp;gt; (sum &amp;lt;= (n * max)%Z)%Z)))).&lt;br /&gt;(* YOU MAY EDIT THE PROOF BELOW *)&lt;br /&gt;intuition.&lt;br /&gt;&lt;br /&gt;Qed.&lt;br /&gt;(* DO NOT EDIT BELOW *)&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;br /&gt;■生成された証明課題をCoqで証明する。&lt;br /&gt;&lt;br /&gt;まぁこれを Coq で証明すれば OK なんですが...。&lt;br /&gt;見た目、すごい定理の様になっていますが、intuition すると3つの証明課題に分離されます。それを ring, omega などを駆使して各個撃破すれば OK です。証明するとこんな感じ。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;(* YOU MAY EDIT THE PROOF BELOW *)&lt;br /&gt;intuition.&lt;br /&gt;Require Import Omega.&lt;br /&gt;Require Import Ring.&lt;br /&gt;      rewrite H8. rewrite H7.&lt;br /&gt;      cut((sum &amp;lt;= (i*get a1 i)%Z)%Z). intro.&lt;br /&gt;        replace ((i+1)%Z*get a1 i)%Z with ((i*get a1 i)%Z + get a1 i)%Z.&lt;br /&gt;          omega.&lt;br /&gt;        ring.&lt;br /&gt;      cut(((i*max)%Z &amp;lt;= (i*get a1 i)%Z)%Z). intro.&lt;br /&gt;        omega.&lt;br /&gt;      destruct i; try omega.&lt;br /&gt;        eapply Zmult_le_compat_l; try omega.&lt;br /&gt;      elim H5. simpl. auto.&lt;br /&gt;  rewrite H7.&lt;br /&gt;    replace ((i+1)*max)%Z with (i*max + max)%Z.&lt;br /&gt;      omega.&lt;br /&gt;    ring.&lt;br /&gt;  replace (n-1+1)%Z with n in H3. auto.&lt;br /&gt;    auto.&lt;br /&gt;  omega.&lt;br /&gt;Qed.&lt;br /&gt;(* DO NOT EDIT BELOW *)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;■まとめ&lt;br /&gt;&lt;br /&gt;Coq を使うことで課題を証明出来ました。今回は事前条件やループ不変条件をマニュアル記載の所与のものとしましたが、実際には正しくかつ充分なそれらを書くのはそれなりに知識が必要です。&lt;br /&gt;ですが、とりあえずWhy3を使用することで、最弱事前条件を自動生成してくれるので、ひたすら定理を証明すれば良く、かなり楽になります。&lt;br /&gt;&lt;br /&gt;■その先の話&lt;br /&gt;&lt;br /&gt;Why3の上に更にKrakatoaを使うことで、Javaプログラムの検証が出来る、という話を&lt;a href="http://qnighy.hatenablog.com/entry/2011/12/12/104640"&gt;Krakatoa and Jessieを用いた、Javaプログラムの正当性＆安全性証明(アルゴリズムもあるよ！)&lt;/a&gt;という記事でqnighyさんがAdvent Calenderの記事に書いていますのでそちらもご覧下さい。Krakatoaを用いたJavaプログラムの検証の場合は、intがZ(Coqの任意桁整数)でなくJavaと同じ32bit整数で扱われるので、より実用的ですが証明が大変です。&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;■宣伝&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;毎月１回週末に、新宿にて形式手法勉強会の&amp;nbsp;&lt;a href="https://groups.google.com/group/fm-forum?hl=ja&amp;amp;pli=1"&gt;Formal Methods Forum&lt;/a&gt;&amp;nbsp;を開催しています。内容は Coq を中心とした各種形式手法（定理証明系とモデル検査など）についての勉強会です。東京近隣の方はぜひご参加を。（あと来年の１、２月の平日夜にCoq講習会を計画してます。もうちょっとしたらFMFとかで告知します。）&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-9105494432647884943?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/9105494432647884943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=9105494432647884943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/9105494432647884943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/9105494432647884943'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/11/why3-how-to-use-why3-theorem-prover.html' title='[Why3] How to Use Why3 (Theorem Prover Advent Calender)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-232249909561959665</id><published>2011-12-15T07:39:00.000+09:00</published><updated>2011-12-15T07:42:12.891+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Blogger'/><category scheme='http://www.blogger.com/atom/ns#' term='MathJax'/><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><title type='text'>[Blogger][LaTeX] Install MathJax</title><content type='html'>&lt;br /&gt;&lt;a href="http://irrep.blogspot.com/2011/07/mathjax-in-blogger-ii.html"&gt;MathJax in Blogger (II)&lt;/a&gt; を参考にMathJaxを使える様にしてみた。&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;$$a^2+b^2=c^2$$&lt;br /&gt;&lt;br /&gt;どうやら使えているみたい。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-232249909561959665?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/232249909561959665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=232249909561959665' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/232249909561959665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/232249909561959665'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/12/bloggerlatex-install-mathjax.html' title='[Blogger][LaTeX] Install MathJax'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8571962109929543062</id><published>2011-12-03T01:00:00.000+09:00</published><updated>2011-12-03T02:55:33.177+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Why3'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Why3] Install of Why3 Tool (Theorem Prover Advent Calender)</title><content type='html'>この記事は&lt;a href="http://partake.in/events/30381166-394a-4fab-a5ea-5984d051de01"&gt;Theorem Proving Advent Calendar 2011&lt;/a&gt;の3日目の記事です。（なお、Advent Calender の参加者も継続募集中です。）&lt;br /&gt;&lt;br /&gt;&lt;a href="http://why3.lri.fr/"&gt;Why3&lt;/a&gt; をMacOS (Snow Leopard) に導入してみました。&lt;br /&gt;Why3 は Why の後継で、Why というのはプログラム検証プラットホームです。Java や C のプログラムに注釈として事前事後条件などを書くと、why 言語という中間言語に一度処理され、Alt-Ergo などの自動証明器や Coq のような証明支援系に適した出力に変換してくれます。さらに上記を統合した GUI フロントエンドを提供します。その辺の話は昔作った発表資料(&lt;a href="http://www.slideshare.net/tmiya/coq-20100208a"&gt;Slideshare&lt;/a&gt;)を参照して下さい。&lt;br /&gt;&lt;br /&gt;■なぜ Why3 を学ぶのか&lt;br /&gt;今年の11月に &lt;a href="https://sites.google.com/site/vstte2012/compet"&gt;VSTTE 2012 Software Verification Competition&lt;/a&gt; という競技ソフトウェア検証イベントがありました。平日開催で忙しかったという理由もありますが、出された問題の多くが手続き型的コードの検証ということもあり、普通の Coq の証明の知識だけでは手が出ませんでした。そこで来年に活かそう、という理由で Why3 を学ぶことにしました。&lt;br /&gt;実際問題として、手続き的に書かれたプログラムについて検証したいという需要は多いと思われます。（たとえ Coq などの定理証明系は純関数型的なコードと相性が良くても。）&lt;br /&gt;Why3 と同様のツールに関しては CFML という OCaml コードの検証ツールについて &lt;a href="http://d.hatena.ne.jp/keigoi/20111111"&gt;@keigoi さんが記事をお書きに&lt;/a&gt;なっていますので、そちらもご覧下さい --- というか CFML もいずれ動かしてみたいです。&lt;br /&gt;&lt;br /&gt;■ Why3 導入&lt;br /&gt;すでに Xcode, macports とか OCaml, Coq は導入済みと仮定します。&lt;br /&gt;&lt;a href="https://gforge.inria.fr/frs/?group_id=2990"&gt;Why3 ダウンロードサイト&lt;/a&gt;よりversion 0.71のtarを入手し、適当なディレクトリで展開します。configure したら色々無いと判ったのでとりあえず導入。ocamlgraph は ports に無いので別途&lt;a href="http://ocamlgraph.lri.fr/"&gt;ここ&lt;/a&gt;から入手。でも CoqIDE 動いてるのになんで &lt;code&gt;lablgtk2 無いの&lt;/code&gt;？&lt;br /&gt;&lt;br /&gt;&lt;code&gt;% ./configure&lt;/code&gt;&lt;br /&gt;&lt;code&gt;略 &lt;/code&gt;&lt;br /&gt;&lt;code&gt;% sudo port install lablgtk2&lt;/code&gt;&lt;code&gt;% sudo port install caml-menhir&lt;br /&gt;% sudo port install rubber&lt;br /&gt;% sudo port install caml-sqlite3&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;ocamlgraph 導入&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% cd ???/ocamlgraph-1.8.1&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% ./configure&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% make&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% sudo make install&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% sudo make install-findlib&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;why3 ディレクトリに戻る&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% ./configure&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Summary&lt;br /&gt;-----------------------------------------&lt;br /&gt;OCaml version&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 3.12.1&lt;br /&gt;OCaml library path&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : /opt/local/lib/ocaml&lt;br /&gt;Verbose make&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : no&lt;br /&gt;Why IDE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : yes &lt;br /&gt;Why bench tool&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : yes&lt;br /&gt;Why documentation&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : yes&lt;br /&gt;Why plugins&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : yes&lt;br /&gt;Coq plugin support&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : no&amp;nbsp; (not yet implemented)&lt;br /&gt;TPTP parser&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : yes&lt;br /&gt;Menhir library&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : no&lt;br /&gt;hypothesis selection&amp;nbsp;&amp;nbsp;&amp;nbsp; : yes&lt;br /&gt;profiling&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : no&lt;br /&gt;localdir&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : no&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% make&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;ここで&amp;nbsp;&lt;/code&gt;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;why3-0.71/src/ide/gmain.ml の GSourceView2 を gSourceView2 に修正など苦労するが結局&lt;/span&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;File "gmain.ml", line 1180, characters 42-43:&lt;br /&gt;Error: Syntax error: ')' expected&lt;br /&gt;File "gmain.ml", line 1180, characters 25-26:&lt;br /&gt;Error: This '(' might be unmatched &lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;などのコンパイルエラーが消えず、GUIは諦めることにする。&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% ./configure --disable-ide&lt;br /&gt;% make clean; make&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% sudo make install &lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;各種ツールが /usr/local/bin/ に導入された。&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;■ 各種自動定理証明器の導入&lt;br /&gt;基本的にどれかで証明出来れば良いと考えると、色々導入した方が有利なんですが、とりあえず Alt-Ergo だけ導入すれば雰囲気は味わえます。どれが一番強力な自動証明器かというのは良く解りません。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://alt-ergo.lri.fr/"&gt;Alt-Ergo&lt;/a&gt; は Why3 のページから辿って、alt-ergo-0.93 の Mac 版をダウンロードするだけ (make 不要)。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cs.nyu.edu/acsys/cvc3/"&gt;CVC3&lt;/a&gt; についても同様にして &lt;a href="http://www.cs.nyu.edu/acsys/cvc3/releases/2.4.1/macosx/cvc3-2.4.1-macosx-optimized-dynamic.tar.gz"&gt;64-bit Intel Mac OS X (Snow Leopard) dynamic library and executable&lt;/a&gt; cvc3 2.4.1 を導入。これは展開するだけ。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://yices.csl.sri.com/"&gt;Yices&lt;/a&gt; も同様に Yices 1.0.31 をダウンロードして展開。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://gappa.gforge.inria.fr/"&gt;Gappa&lt;/a&gt; も同様に gappa 0.15.1 をダウンロード。INSTALL を読むと前提が GMP, MPFR, Boost なのでそれぞれダウンロードして導入。GMPは入手先サイトが無くなっていたので ports で代用し、&lt;code&gt;&amp;nbsp;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% sudo port install gmp&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% sudo port install mpfr&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% sudo port install boost&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% ./configure&lt;/code&gt;&lt;br /&gt;&lt;code&gt;GMPが見つからず失敗&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% ./configure "CPPFLAGS=-I/opt/local/include" "LDFLAGS=-L/opt/local/lib"&lt;br /&gt;成功&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% make&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% sudo make install&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;/code&gt;で代用。&lt;br /&gt;&lt;br /&gt;■構成&lt;br /&gt;インストールしたcvc3などにPATHを通して&lt;br /&gt;&lt;code&gt;% why3config --detect&lt;/code&gt;&lt;br /&gt;します。なんかyicesが未サポートヴァージョン、cvc3が動かず、Alt-Ergo, Gappa, Coq だけという状況。一度構成したら&lt;br /&gt;&lt;code&gt;% why3 --list-provers&lt;br /&gt;Known provers:&lt;br /&gt;&amp;nbsp; alt-ergo (Alt-Ergo)&lt;br /&gt;&amp;nbsp; coq (Coq)&lt;br /&gt;&amp;nbsp; gappa (Gappa)&lt;br /&gt;&amp;nbsp; yices (Yices)&lt;/code&gt;&lt;br /&gt;と表示されます。証明器を追加したら再度同様に構成します。&lt;br /&gt;&lt;br /&gt;■実行例&lt;br /&gt;&lt;code&gt;examples/&lt;/code&gt;に入っている &lt;br /&gt;&lt;br /&gt;&lt;code&gt;% cat hello_proof.why &lt;br /&gt;theory HelloProof "My very first Why3 theory"&lt;br /&gt;&lt;br /&gt;&amp;nbsp; goal G1 : true&lt;br /&gt;&lt;br /&gt;&amp;nbsp; goal G2 : (true -&amp;gt; false) /\ (true \/ false)&lt;br /&gt;&lt;br /&gt;&amp;nbsp; use import int.Int&lt;br /&gt;&lt;br /&gt;&amp;nbsp; goal G3: forall x:int. x*x &amp;gt;= 0&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;%&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;を試してみましょう。ちなみにG2はそもそも間違っているので自動証明失敗して当然です。&lt;br /&gt;Coq については出力先ディレクトリを予め作成しておいて、-o オプションで指定します。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;% why3 -P alt-ergo hello_proof.why &lt;br /&gt;hello_proof.why HelloProof G1 : Valid (0.03s)&lt;br /&gt;hello_proof.why HelloProof G2 : Unknown: Unknown (0.04s)&lt;br /&gt;hello_proof.why HelloProof G3 : Valid (0.03s)&lt;br /&gt;% why3 -P gappa hello_proof.why&lt;br /&gt;hello_proof.why HelloProof G1 : Valid (0.00s)&lt;br /&gt;hello_proof.why HelloProof G2 : Unknown: Unknown (0.00s)&lt;br /&gt;hello_proof.why HelloProof G3 : Unknown: Unknown (0.00s)&lt;br /&gt;% why3 -P yices hello_proof.why&lt;br /&gt;hello_proof.why HelloProof G1 : Valid (0.00s)&lt;br /&gt;hello_proof.why HelloProof G2 : Unknown: Unknown (0.00s)&lt;br /&gt;hello_proof.why HelloProof G3 : Unknown: Unknown (0.00s)&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;% mkdir hello&lt;/pre&gt;&lt;pre&gt;% why3 -P coq -o hello hello_proof.why&lt;br /&gt;% ls hello&lt;br /&gt;hello_proof_HelloProof_G1.v hello_proof_HelloProof_G3.v&lt;br /&gt;hello_proof_HelloProof_G2.v &lt;/pre&gt;&lt;pre&gt;% cat hello/hello_proof_HelloProof_G2.v &lt;br /&gt;(* This file is generated by Why3's Coq driver *)&lt;br /&gt;(* Beware! Only edit allowed sections below    *)&lt;br /&gt;Require Import ZArith.&lt;br /&gt;Require Import Rbase.&lt;br /&gt;(* YOU MAY EDIT THE CONTEXT BELOW *)&lt;br /&gt;&lt;br /&gt;(* DO NOT EDIT BELOW *)&lt;br /&gt;&lt;br /&gt;Theorem G2 : False.&lt;br /&gt;(* YOU MAY EDIT THE PROOF BELOW *)&lt;br /&gt;intuition.&lt;br /&gt;&lt;br /&gt;Qed.&lt;br /&gt;(* DO NOT EDIT BELOW *)&lt;br /&gt;&lt;br /&gt;% &lt;/pre&gt;&lt;br /&gt;G2を下記の様に正しく修正すると、&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;% grep G2 hello_proof.why&lt;br /&gt;&amp;nbsp; goal G2 : (true -&amp;gt; false) \/ (true \/ false)&lt;/code&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;% why3 -P alt-ergo hello_proof.why&lt;/span&gt;&lt;br /&gt;&lt;code&gt;hello_proof.why HelloProof G1 : Valid (0.03s)&lt;br /&gt;hello_proof.why HelloProof G2 : Valid (0.03s)&lt;br /&gt;hello_proof.why HelloProof G3 : Valid (0.03s)&lt;br /&gt;%&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;上記の様に自動証明に成功します。ツールの導入が終わったので、次回は Why3 を用いたプログラム開発に付いて説明します。&lt;br /&gt;&lt;br /&gt;■宣伝&lt;br /&gt;毎月１回週末に、新宿にて形式手法勉強会の &lt;a href="https://groups.google.com/group/fm-forum?hl=ja&amp;amp;pli=1"&gt;Formal Methods Forum&lt;/a&gt; を開催しています。内容は Coq を中心とした各種形式手法（定理証明系とモデル検査など）についての勉強会です。東京近隣の方はぜひご参加を。&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8571962109929543062?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8571962109929543062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8571962109929543062' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8571962109929543062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8571962109929543062'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/12/why3-install-of-why3-tool-theorem.html' title='[Why3] Install of Why3 Tool (Theorem Prover Advent Calender)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-6000583862361516623</id><published>2011-11-03T17:02:00.003+09:00</published><updated>2011-11-03T17:04:07.516+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] TypeClass vs Record</title><content type='html'>&lt;p&gt;CoqでClass/Instance (型クラス) と Record と何が違うの？、というのは私も明確に理解出来てなかったのですが、2011/11/01前後のCoq-Clubの"What are type classes?"というスレッドで色々解説されてます。&lt;/p&gt;&lt;p&gt;まず実装自体は "Type classes are a thin layer on top of dependent records (although some special type classes are actually not records but raw definitions)." らしく、Record の上に構文糖があるみたいなものらしい。&lt;/p&gt;&lt;p&gt;そして、"Type classes allow you to specify an abstract "interface" for which you want the system to *automatically* find an implementation. Hence the main difference: type class instances (terms of a record type) are registered in a special "auto" database. This database is then used to resolve the class requirements you specify in for example a lemma." ということで、抽象的な interface への操作に対しても色々 implicit な実装を自動で探してくれるということみたい。&lt;/p&gt;&lt;p&gt;違いが判りやすいサンプルコードは下記の様になります。&lt;/p&gt;まず EqDec という decidability を持つ Class を定義し、次いで EqDec nat という具体的な instance を定義します。最後に EqDec の定義を見ると実体は単なる Record になっていることが判ります。&lt;pre&gt;&lt;br /&gt;Class EqDec (A:Type) := {&lt;br /&gt; eq_dec: forall (x y:A), {x=y}+{x&lt;&gt;y}&lt;br /&gt;}.&lt;br /&gt;Instance EqDec_nat : EqDec nat.&lt;br /&gt;constructor. decide equality.&lt;br /&gt;Qed.&lt;br /&gt;Print EqDec.&lt;br /&gt;(* Record EqDec (A : Type) : Type := Build_EqDec&lt;br /&gt;  { eq_dec : forall x y : A, {x = y} + {x &lt;&gt; y} } *)&lt;br /&gt;&lt;/pre&gt;同じことを Record で書きます。&lt;pre&gt;&lt;br /&gt;Record EqDec' (A : Type) : Type := Build_EqDec'&lt;br /&gt; { eq_dec' : forall x y : A, {x = y} + {x &lt;&gt; y} }.&lt;br /&gt;Definition EqDec'_nat : EqDec' nat.&lt;br /&gt;constructor. decide equality.&lt;br /&gt;Qed.&lt;br /&gt;&lt;/pre&gt;eq_dec と eq_dec' は実際、同じ型を持ちます。&lt;pre&gt;&lt;br /&gt;Check @eq_dec.&lt;br /&gt;(* eq_dec : forall A : Type, EqDec A -&gt; forall x y : A, {x = y} + {x &lt;&gt; y} *)&lt;br /&gt;Check @eq_dec'.&lt;br /&gt;(* eq_dec' : forall A : Type, EqDec' A -&gt; forall x y : A, {x = y} + {x &lt;&gt; y} *)&lt;br /&gt;&lt;/pre&gt;しかし実際に使うときの自動推論の能力に違いが出ます。&lt;pre&gt;&lt;br /&gt;Definition eq_nat_dec :  forall (x y:nat), {x=y}+{x&lt;&gt;y} := @eq_dec nat _. &lt;br /&gt;Print eq_nat_dec.&lt;br /&gt;(* eq_nat_dec = eq_dec : forall x y : nat, {x = y} + {x &lt;&gt; y} *)&lt;br /&gt;Definition eq_nat_dec :  forall (x y:nat), {x=y}+{x&lt;&gt;y} := @eq_dec' nat _.&lt;br /&gt;(* Error: Cannot infer this placeholder. *)&lt;br /&gt;&lt;/pre&gt;これを見る限り、使い方 (interface/implementationの分離にtype classを使う) とかを別にすると、実装的には単に便利な自動推論がついているだけ、ということみたいです。あと、この発表資料はCoqにおけるType Classの良い説明かも。&lt;a href="http://mattam.org/research/publications/First-Class_Type_Classes-TPHOLs-200808.pdf"&gt;http://mattam.org/research/publications/First-Class_Type_Classes-TPHOLs-200808.pdf&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-6000583862361516623?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/6000583862361516623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=6000583862361516623' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6000583862361516623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6000583862361516623'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/11/coq-typeclass-vs-record.html' title='[Coq] TypeClass vs Record'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5977320041383624985</id><published>2011-10-28T18:24:00.000+09:00</published><updated>2011-10-28T18:24:19.402+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Monads in Coq</title><content type='html'>社内勉強会でMonad入門の話をして、その時にCoqを用いて説明しました。&lt;br/&gt;あまりHaskellに慣れてないのでCoq使ったんですが、CoqではMonad則を証明する必要があるので、実は寧ろ説明に適していました。&lt;br/&gt;HaskellだとMonad則がなぜ必要なのか示すのが面倒そう（任意の関数、なんてのはQuickCheckでも作れ無さそうな気がする）ですが、CoqではそもそもMonad則を満たすことを示さないと、Monadを使えません。&lt;br/&gt;サンプルコードでは、&lt;ul&gt;&lt;li&gt;Maybeモナド、Listモナドについて示してあります。&lt;/li&gt;&lt;li&gt;サザエさんの家族構成を用いて、MaybeやListのサンプルコードを書いています。&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;br /&gt;Class Monad (M:Type -&gt; Type):Type := {&lt;br /&gt;  return' : forall {A}, A -&gt; M A;&lt;br /&gt;  bind : forall {A B}, M A -&gt; (A -&gt; M B) -&gt; M B;&lt;br /&gt;  left_unit : forall A B (a:A)(f:A -&gt; M B),&lt;br /&gt;    bind (return' a) f = f a;&lt;br /&gt;  right_unit : forall A (ma:M A),&lt;br /&gt;    bind ma return' = ma;&lt;br /&gt;  assoc : forall A B C (ma:M A)(f:A -&gt; M B)&lt;br /&gt;    (g:B -&gt; M C), bind (bind ma f ) g =&lt;br /&gt;    bind ma (fun a =&gt; bind (f a) g)&lt;br /&gt;}.&lt;br /&gt;Notation "m &gt;&gt;= f" := &lt;br /&gt;  (bind m f) (left associativity, at level 49).&lt;br /&gt;&lt;br /&gt;Notation "'do' a &lt;- e ; c" := &lt;br /&gt;  (e &gt;&gt;= (fun a =&gt; c)) &lt;br /&gt;  (at level 59, right associativity).&lt;br /&gt;&lt;br /&gt;Instance Maybe : Monad option := {&lt;br /&gt;  return' A a := Some a;&lt;br /&gt;  bind A B ma f :=&lt;br /&gt;    match ma with&lt;br /&gt;    | None =&gt; None&lt;br /&gt;    | Some a =&gt; f a&lt;br /&gt;    end&lt;br /&gt;}.&lt;br /&gt;Proof.&lt;br /&gt;  intros; auto.&lt;br /&gt;  intros; destruct ma; auto.&lt;br /&gt;  intros; destruct ma; [destruct (f a)|]; auto.&lt;br /&gt;Defined.&lt;br /&gt;&lt;br /&gt;Eval compute in (Some 1 &gt;&gt;= (fun x =&gt; return' (x + 1))).&lt;br /&gt;Eval compute in (None &gt;&gt;= (fun x =&gt; return' (x + 1))).&lt;br /&gt;&lt;br /&gt;Inductive Isono:Set :=&lt;br /&gt;  Namihei | Fune | Masuo | Sazae | Katsuo | Wakame | Tara.&lt;br /&gt;&lt;br /&gt;Definition father(x:Isono):option Isono :=&lt;br /&gt;match x with&lt;br /&gt;| Tara =&gt; Some Masuo&lt;br /&gt;| Sazae | Katsuo | Wakame =&gt; Some Namihei&lt;br /&gt;| _ =&gt; None&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;Definition mother(x:Isono):option Isono :=&lt;br /&gt;match x with&lt;br /&gt;| Tara =&gt; Some Sazae&lt;br /&gt;| Sazae | Katsuo | Wakame =&gt; Some Fune&lt;br /&gt;| _ =&gt; None&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;Definition f_of_m(s:Isono):option Isono :=&lt;br /&gt;match (mother s) with&lt;br /&gt;| None =&gt; None&lt;br /&gt;| Some x =&gt; father x&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;Definition f_of_m'(s:Isono):option Isono :=&lt;br /&gt;  do x &lt;- mother s;&lt;br /&gt;  father x.&lt;br /&gt;&lt;br /&gt;Eval compute in (f_of_m' Tara).&lt;br /&gt;Eval compute in (f_of_m' Katsuo).&lt;br /&gt;&lt;br /&gt;Require Import List.&lt;br /&gt;Lemma flat_map_app : forall (A B:Type)(xs ys:list A)(f:A -&gt; list B),&lt;br /&gt; flat_map f (xs++ys) = flat_map f xs ++ flat_map f ys.&lt;br /&gt;Proof.&lt;br /&gt; induction xs.&lt;br /&gt;   simpl. auto.&lt;br /&gt;   simpl. intros. erewrite IHxs. erewrite app_ass. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Instance List : Monad list := {&lt;br /&gt;  return' A x := x :: nil;&lt;br /&gt;  bind A B m f := flat_map f m&lt;br /&gt;}.&lt;br /&gt;Proof.&lt;br /&gt;(* left_unit *)&lt;br /&gt;intros A B a f. simpl. erewrite &lt;- app_nil_end. auto.&lt;br /&gt;(* right_unit *)&lt;br /&gt;intros A m. induction m.&lt;br /&gt; simpl. auto.&lt;br /&gt; simpl. rewrite IHm. auto.&lt;br /&gt;(* assoc *)&lt;br /&gt;intros A B C m f g. induction m.&lt;br /&gt; simpl. auto.&lt;br /&gt; simpl. rewrite &lt;- IHm.&lt;br /&gt; erewrite flat_map_app. auto.&lt;br /&gt;Defined.&lt;br /&gt;&lt;br /&gt;Definition children(x:Isono):list Isono :=&lt;br /&gt;match x with&lt;br /&gt;| Namihei | Fune =&gt; Sazae::Katsuo::Wakame::nil&lt;br /&gt;| Sazae | Masuo =&gt; Tara::nil&lt;br /&gt;| _ =&gt; nil&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;Eval compute in (children Fune).&lt;br /&gt;Eval compute in (children Katsuo).&lt;br /&gt;&lt;br /&gt;Definition grandchildren(x:Isono):list Isono :=&lt;br /&gt;  do y &lt;- children x;&lt;br /&gt;     children y. &lt;br /&gt;&lt;br /&gt;Eval compute in (grandchildren Fune).&lt;br /&gt;Eval compute in (grandchildren Katsuo).&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5977320041383624985?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5977320041383624985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5977320041383624985' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5977320041383624985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5977320041383624985'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/10/coq-monads-in-coq.html' title='[Coq] Monads in Coq'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-6044205297215389970</id><published>2011-10-10T17:07:00.001+09:00</published><updated>2011-10-10T17:07:38.844+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PFDS'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq][PFDS] How to use Module in Coq</title><content type='html'>今日のFormal Methods Forumでは、CoqでPFDS(Purely Functional Data Structure)を、というのをみんなで実施しました。参加者の誰もがMLのmodule systemになれておらず色々苦労しましたが、とりあえずこんな感じのコードになりました。まず Exercise 2.1 の suffixes ですが、これは簡単。&lt;pre&gt;Fixpoint suffixes{A:Set}(xs:list A):list (list A) :=&lt;br /&gt;match xs with&lt;br /&gt;| nil =&gt; nil&lt;br /&gt;| _::xs' =&gt; xs :: (suffixes xs')&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;Eval compute in (suffixes (1::2::3::4::nil)).&lt;br /&gt;(* = (1 :: 2 :: 3 :: 4 :: nil)&lt;br /&gt;       :: (2 :: 3 :: 4 :: nil) :: (3 :: 4 :: nil) :: (4 :: nil) :: nil&lt;br /&gt;     : list (list nat) *)&lt;/pre&gt;consする回数を数えるヴァージョンと、回数がO(n) (というかn) である証明。&lt;pre&gt;Fixpoint suffixes' {A:Set}(xs:list A)(c:nat):&lt;br /&gt;  (nat * (list (list A)))%type :=&lt;br /&gt;match xs with&lt;br /&gt;| nil =&gt; (0,nil)&lt;br /&gt;| _::xs' =&gt;&lt;br /&gt;  let (c',ys) := (suffixes' xs' c)&lt;br /&gt;  in (c'+1, xs::ys)&lt;br /&gt;end.&lt;br /&gt;Eval compute in (suffixes' (1::2::3::4::nil) 0).&lt;br /&gt;&lt;br /&gt;Theorem suffixes'_length : forall (A:Set)(xs:list A),&lt;br /&gt;  fst (suffixes' xs 0) = length xs.&lt;br /&gt;Proof.&lt;br /&gt;  intros A xs.&lt;br /&gt;  induction xs.&lt;br /&gt;    simpl. trivial.&lt;br /&gt;    simpl. destruct (suffixes' xs 0). simpl.&lt;br /&gt;    simpl in IHxs. rewrite &lt;- IHxs.  omega.&lt;br /&gt;Qed. &lt;/pre&gt;Coq の module の使い方はこんな感じ。まず SET signature のモジュールを定義します。予約語回避のためあちこちに _ を追加します。&lt;pre&gt;Module Type SET.&lt;br /&gt;  Parameter Elem : Set.&lt;br /&gt;  Parameter Set_ : Set.&lt;br /&gt;  Parameter empty : Set_.&lt;br /&gt;  Parameter insert : Elem -&gt; Set_ -&gt; Set_.&lt;br /&gt;  Parameter member : Elem -&gt; Set_ -&gt; bool.&lt;br /&gt;End SET.&lt;/pre&gt;次いで、ORDERED signature を定義します。&lt;pre&gt;Module Type ORDERED.&lt;br /&gt;  Parameter T : Set.&lt;br /&gt;  Parameter eq_ : T -&gt; T -&gt; bool.&lt;br /&gt;  Parameter lt_ : T -&gt; T -&gt; bool.&lt;br /&gt;  Parameter gt_ : T -&gt; T -&gt; bool.&lt;br /&gt;End ORDERED.&lt;/pre&gt;次が、ORDERED な型のUnbalancedSet を定義します。ElementはORDERED signatureを満たすものです。SETのsignatureを持つので&lt;code&gt;&lt;:&lt;/code&gt;を使って定義します。&lt;pre&gt;Module Type UnbalancedSet (Element:ORDERED) &lt;: SET.&lt;br /&gt;  Definition Elem := Element.T.&lt;br /&gt;  Inductive Tree :=&lt;br /&gt;  | E : Tree&lt;br /&gt;  | T : Tree -&gt; Elem -&gt; Tree -&gt; Tree.&lt;br /&gt;  Definition Set_ := Tree.&lt;br /&gt;  Definition empty := E.&lt;br /&gt;  Fixpoint member (x:Elem)(tr:Tree) :=&lt;br /&gt;  match tr with&lt;br /&gt;  | E =&gt; false&lt;br /&gt;  | T a y b =&gt; &lt;br /&gt;    if (Element.lt_ x y) then (member x a)&lt;br /&gt;    else (if (Element.lt_ y x) then (member x b)&lt;br /&gt;          else true )&lt;br /&gt;  end.&lt;br /&gt;  Fixpoint insert (x:Elem)(tr:Tree) :=&lt;br /&gt;  match tr with&lt;br /&gt;  | E =&gt; T E x E&lt;br /&gt;  | T a y b =&gt;&lt;br /&gt;    if (Element.lt_ x y) then (T (insert x a) y b)&lt;br /&gt;    else (if (Element.lt_ y x) then (T a y (insert x b))&lt;br /&gt;          else tr)&lt;br /&gt;  end.&lt;br /&gt;End UnbalancedSet.&lt;/pre&gt;と定義します。ORDERED の具体例として NAT を作ります。&lt;pre&gt;Fixpoint blt_nat (x y:nat):bool :=&lt;br /&gt;match x,y with&lt;br /&gt;| O,O =&gt; false&lt;br /&gt;| O,_ =&gt; true&lt;br /&gt;| _,O =&gt; false&lt;br /&gt;| S x',S y' =&gt; blt_nat x' y'&lt;br /&gt;end.&lt;br /&gt;Eval compute in (blt_nat 2 2). (* false *)&lt;br /&gt;Eval compute in (blt_nat 2 3). (* true *)&lt;br /&gt;Eval compute in (blt_nat 3 2). (* false *)&lt;br /&gt;Definition bgt_nat (x y:nat):bool := blt_nat y x.&lt;br /&gt;&lt;br /&gt;Module NAT &lt;: ORDERED.&lt;br /&gt;  Definition T := nat.&lt;br /&gt;  Definition eq_ := beq_nat.&lt;br /&gt;  Definition lt_ := blt_nat.&lt;br /&gt;  Definition gt_ := bgt_nat.&lt;br /&gt;End NAT.&lt;/pre&gt;そして、Element:ORDERED として NAT&lt;:ORDERED を取る UNSet を定義します。Include を使うのが大事なポイントです。&lt;pre&gt;(* Unbalanced Nat Set *)&lt;br /&gt;Module UNSet &lt;: (UnbalancedSet NAT).&lt;br /&gt;Include (UnbalancedSet NAT).&lt;br /&gt;End UNSet.&lt;/pre&gt;最後にそれを使ってみます。&lt;pre&gt;Definition E := UNSet.E.&lt;br /&gt;Print E.&lt;br /&gt;Definition T := UNSet.T.&lt;br /&gt;Print T.&lt;br /&gt;Print UNSet.Elem.&lt;br /&gt;Print NAT.T.&lt;br /&gt;Eval compute in (T E 1 E).&lt;br /&gt;Eval compute in (UNSet.member 1 (T E 1 E)).&lt;br /&gt;Eval compute in (UNSet.insert 2 (T E 1 E)).&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-6044205297215389970?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/6044205297215389970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=6044205297215389970' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6044205297215389970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6044205297215389970'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/10/coqpfds-how-to-use-module-in-coq.html' title='[Coq][PFDS] How to use Module in Coq'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-4624655874059177100</id><published>2011-09-04T00:43:00.001+09:00</published><updated>2011-09-04T00:45:50.591+09:00</updated><title type='text'>[Coq] Ring in Coq</title><content type='html'>&lt;a href="http://partake.in/events/989bf10a-d5f0-4fcc-ba1f-f152fe2f7072"&gt;スタート代数&lt;/a&gt;という勉強会に参加してきました。そこで出された宿題のうち１問を Coq で証明してみました。まぁこの程度簡単な証明なら Coq でも出来るけど、という感じです。Coq で証明するとはどんな感じかの参考になればと思います。&lt;pre&gt;&lt;br /&gt;Section Ring.&lt;br /&gt;(* R : ring *)&lt;br /&gt;Axiom R:Set.&lt;br /&gt;(* plus *)&lt;br /&gt;Axiom plus : R -&gt; R -&gt; R.&lt;br /&gt;Notation "a + b" := (plus a b).&lt;br /&gt;Axiom plus_assoc : forall a b c:R, (a+b)+c=a+(b+c).&lt;br /&gt;Axiom plus_comm : forall a b:R, a+b=b+a.&lt;br /&gt;Axiom zero : R.&lt;br /&gt;Notation "0" := zero.&lt;br /&gt;Axiom plus_unit_l : forall a:R, 0 + a = a.&lt;br /&gt;Axiom plus_unit_r : forall a:R, a + 0 = a.&lt;br /&gt;Axiom minus : R -&gt; R.&lt;br /&gt;Notation "^ a" := (minus a) (at level 90).&lt;br /&gt;Axiom plus_inv_l : forall a:R, (^a) + a = 0. &lt;br /&gt;Axiom plus_inv_r : forall a:R, a + (^a) = 0. &lt;br /&gt;(* mult *)&lt;br /&gt;Axiom mult : R -&gt; R -&gt; R.&lt;br /&gt;Notation "a * b" := (mult a b).&lt;br /&gt;Axiom mult_assoc : forall a b c:R, (a*b)*c=a*(b*c).&lt;br /&gt;Axiom one : R.&lt;br /&gt;Notation "1" := one.&lt;br /&gt;Axiom mult_unit_l : forall a:R, 1 * a = a.&lt;br /&gt;Axiom mult_unit_r : forall a:R, a * 1 = a.&lt;br /&gt;(* commutative ring *)&lt;br /&gt;Axiom mult_comm : forall a b:R, a*b = b*a.&lt;br /&gt;(* distributive *)&lt;br /&gt;Axiom distr_l : forall a b c:R, a*(b+c) = a*b + a*c.&lt;br /&gt;Axiom distr_r : forall a b c:R, (a+b)*c = a*c + b*c.&lt;br /&gt;&lt;br /&gt;Lemma rm_plus_l : forall a b c:R, a+b=a+c -&gt; b=c.&lt;br /&gt;Proof.&lt;br /&gt;  intros a b c ab_ac.&lt;br /&gt;  specialize(plus_assoc (^a) a b). intro H.&lt;br /&gt;  rewrite ab_ac in H.&lt;br /&gt;  rewrite &lt;- plus_assoc in H.&lt;br /&gt;  rewrite plus_inv_l in H.&lt;br /&gt;  repeat rewrite plus_unit_l in H.&lt;br /&gt;  assumption.&lt;br /&gt;Qed.&lt;br /&gt;Theorem mult_a_0 : forall a:R, a * 0 = 0.&lt;br /&gt;Proof.&lt;br /&gt;  intro a.&lt;br /&gt;  assert(H: a*(0+0) = a*0 + 0).&lt;br /&gt;    rewrite plus_unit_l. rewrite plus_unit_r. reflexivity.&lt;br /&gt;  rewrite distr_l in H. &lt;br /&gt;  apply(rm_plus_l (a*0) (a*0) 0). assumption.&lt;br /&gt;Qed.&lt;br /&gt;End Ring.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-4624655874059177100?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/4624655874059177100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=4624655874059177100' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4624655874059177100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4624655874059177100'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/09/coq-ring-in-coq.html' title='[Coq] Ring in Coq'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-4596755775261105914</id><published>2011-09-02T14:23:00.001+09:00</published><updated>2011-09-02T14:23:15.552+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='separation logic'/><title type='text'>[separation logic] jStar: Bringing separation logic to Java</title><content type='html'>&lt;a href="http://www.jstarverifier.org/"&gt;jStar: Bringing separation logic to Java&lt;/a&gt;Java Programに対してseparation logicを使って検証するというもので、事前事後条件を与えると、ループ不変条件は自動的に計算してくれるらしい（&lt;i&gt;"Loop invariants are computed automatically by means of abstract interpretation. "&lt;/i&gt;）論文(PDF)：&lt;a href="http://www.cl.cam.ac.uk/~mjp41/frp39distefano.pdf"&gt;jStar: Towards Practical Verification for Java&lt;/a&gt;チュートリアル(PDF): &lt;a href="http://www.jstarverifier.org/jstar.tutorial.pdf"&gt;How to Verify Java Program with jStar: a Tutorial&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-4596755775261105914?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/4596755775261105914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=4596755775261105914' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4596755775261105914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4596755775261105914'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/09/separation-logic-jstar-bringing.html' title='[separation logic] jStar: Bringing separation logic to Java'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5343038014281298239</id><published>2011-08-26T00:40:00.002+09:00</published><updated>2011-08-26T00:46:53.693+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Category in Coq</title><content type='html'>先日、&lt;a href="http://atnd.org/events/17725"&gt;スタートCoqで圏論 in honor of こんさん&lt;/a&gt;というイベントがあり、その時に書いたコード。ConCaTというライブラリを使い、オブジェクトが２つ、その間に射が１つという圏を書いてみた、というものです。&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Add LoadPath "~/coq/ConCat/ConCaT" as ConCaT.&lt;br /&gt;Print LoadPath.&lt;br /&gt;Require Import ConCaT.CATEGORY_THEORY.CATEGORY.Category.&lt;br /&gt;&lt;br /&gt;Inductive Two_ob : Type := Ob_A | Ob_B.&lt;br /&gt;Inductive Two_mor : Two_ob -&gt; Two_ob -&gt; Type :=&lt;br /&gt;| Id_A : Two_mor Ob_A Ob_A&lt;br /&gt;| Id_B : Two_mor Ob_B Ob_B&lt;br /&gt;| Mor_AB : Two_mor Ob_A Ob_B.&lt;br /&gt;Section equal_two_mor.&lt;br /&gt;  Variable a b:Two_ob.&lt;br /&gt;&lt;br /&gt;  Definition Equal_Two_mor(f g:Two_mor a b) := True.&lt;br /&gt;  Check Equal_Two_mor.&lt;br /&gt;  (* Two_mor a b -&gt; Two_mor a b -&gt; Prop *)&lt;br /&gt;  Lemma Equal_Two_mor_equiv : Equivalence Equal_Two_mor.&lt;br /&gt;  Proof.&lt;br /&gt;    unfold Equal_Two_mor.&lt;br /&gt;    apply Build_Equivalence.&lt;br /&gt;     unfold Reflexive. intro x. auto.&lt;br /&gt;     apply Build_Partial_equivalence.&lt;br /&gt;       unfold Transitive. intros. auto.&lt;br /&gt;       unfold Symmetric. intros. auto.&lt;br /&gt;  Qed.&lt;br /&gt;  Canonical Structure Two_mor_setoid : Setoid :=&lt;br /&gt;    Equal_Two_mor_equiv.&lt;br /&gt;End equal_two_mor.&lt;br /&gt;Definition Comp_Two_mor : forall a b c:Two_ob,&lt;br /&gt;  Two_mor_setoid a b -&gt; Two_mor_setoid b c -&gt;&lt;br /&gt;  Two_mor_setoid a c.&lt;br /&gt;Proof.&lt;br /&gt;  intros a b c Sab Sbc.&lt;br /&gt;  inversion Sab.&lt;br /&gt;    inversion Sbc.&lt;br /&gt;      apply Id_A. &lt;br /&gt;      rewrite &lt;- H0 in H1. discriminate H1.&lt;br /&gt;      apply Mor_AB. &lt;br /&gt;    inversion Sbc.&lt;br /&gt;      rewrite &lt;- H0 in H1. discriminate H1.&lt;br /&gt;      apply Id_B. &lt;br /&gt;      rewrite &lt;- H0 in H1. discriminate H1.&lt;br /&gt;    inversion Sbc.&lt;br /&gt;      rewrite &lt;- H0 in H1. discriminate H1.&lt;br /&gt;      apply Mor_AB.&lt;br /&gt;      rewrite &lt;- H0 in H1. discriminate H1.&lt;br /&gt;Defined.&lt;br /&gt;&lt;br /&gt;Lemma Comp_Two_mor_congl : Congl_law Comp_Two_mor.&lt;br /&gt;Proof.&lt;br /&gt;  unfold Congl_law. intros. simpl.&lt;br /&gt;  unfold Two_mor_setoid in *.&lt;br /&gt;  unfold Equal_Two_mor.&lt;br /&gt;  auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma Comp_Two_mor_congr : Congr_law Comp_Two_mor.&lt;br /&gt;Proof.&lt;br /&gt;  unfold Congr_law. intros. simpl.&lt;br /&gt;  unfold Two_mor_setoid in *.&lt;br /&gt;  unfold Equal_Two_mor.&lt;br /&gt;  auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Definition Comp_Two :=&lt;br /&gt;  Build_Comp Comp_Two_mor_congl Comp_Two_mor_congr.&lt;br /&gt;&lt;br /&gt;Lemma Assoc_Two : Assoc_law Comp_Two.&lt;br /&gt;Proof.&lt;br /&gt;  unfold Assoc_law. intros. simpl in *.&lt;br /&gt;  unfold Equal_Two_mor in *. auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Definition Id_Two (a:Two_ob) : Two_mor_setoid a a :=&lt;br /&gt;match a as a0 return (Two_mor a0 a0) with&lt;br /&gt;| Ob_A =&gt; Id_A&lt;br /&gt;| Ob_B =&gt; Id_B&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;Lemma Idl_Two : Idl_law Comp_Two Id_Two.&lt;br /&gt;Proof.&lt;br /&gt;  unfold Idl_law; simpl.&lt;br /&gt;  unfold Comp_Two; unfold Id_Two; unfold Equal_Two_mor; simpl.&lt;br /&gt;  intros; auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma Idr_Two : Idr_law Comp_Two Id_Two.&lt;br /&gt;Proof.&lt;br /&gt;  unfold Idr_law; simpl.&lt;br /&gt;  unfold Comp_Two; unfold Id_Two; unfold Equal_Two_mor; simpl.&lt;br /&gt;  intros; auto.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Canonical Structure Two := Build_Category Assoc_Two Idl_Two Idr_Two.&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5343038014281298239?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5343038014281298239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5343038014281298239' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5343038014281298239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5343038014281298239'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/08/coq-category-in-coq.html' title='[Coq] Category in Coq'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-6475922250204042241</id><published>2011-06-04T22:55:00.002+09:00</published><updated>2011-06-04T23:03:14.370+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Type Class in Coq</title><content type='html'>　形式手法勉強会の&lt;a href="http://partake.in/events/dfc10138-1c40-449a-84eb-121944653e58"&gt;Formal Methods Forum #16&lt;/a&gt;で、Monadを例にとってCoqでのtype-classを使い方を紹介しました。&lt;br /&gt;&lt;br /&gt;　発表資料は&lt;a href="http://www.slideshare.net/tmiya/typeclass"&gt;http://www.slideshare.net/tmiya/typeclass&lt;/a&gt;&lt;br /&gt;　練習課題の答えは、&lt;a href="http://ideone.com/oANlm"&gt;http://ideone.com/oANlm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;です。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-6475922250204042241?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/6475922250204042241/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=6475922250204042241' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6475922250204042241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6475922250204042241'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/06/coq-type-class-in-coq.html' title='[Coq] Type Class in Coq'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2215949222064957430</id><published>2011-04-12T07:25:00.002+09:00</published><updated>2011-04-12T07:35:00.078+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Event][FM] Formal Methods Forum #15 on 4/23</title><content type='html'>第15回FormalMethods勉強会を 4/23(Sat) に開催します。&lt;br /&gt;参加登録は下記 ATND からお願いします。&lt;br /&gt;&lt;a href="http://atnd.org/events/13673"&gt;http://atnd.org/events/13673&lt;/a&gt;&lt;br /&gt;今回は Monad 特集らしいです。&lt;br /&gt;&lt;br /&gt;今回は Coq 関係では&lt;ul&gt;&lt;br /&gt;&lt;li&gt; Coq の型クラスを使って Monad を実装&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Coq 未経験者向けのチュートリアルを書いたので、他の方に見て頂く&lt;br /&gt;&lt;/ul&gt;を予定してます。&lt;br /&gt;&lt;br /&gt;Coq 未経験者の方は、その旨を ATND 参加時に書いて頂ければ、当日の内容を変更して対応出来る様に致します。ノートパソコン持参を推奨します。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2215949222064957430?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2215949222064957430/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2215949222064957430' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2215949222064957430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2215949222064957430'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/04/eventfm-formal-methods-forum-15-on-423.html' title='[Event][FM] Formal Methods Forum #15 on 4/23'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3087478357950901775</id><published>2011-04-12T07:11:00.003+09:00</published><updated>2011-04-12T07:22:47.456+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Event'/><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq][Formal Methods] Proof Assistant Day 2011 on 9/25(Sun)</title><content type='html'>　今年の９月は東京で &lt;a href="ttp://www.icfpconference.org/icfp2011/"&gt;ICFP 2011&lt;/a&gt; が開催されることもあり、その前後の週末も公式/非公式な関数型言語イベントが多数開催される見込みです。&lt;br /&gt;&lt;br /&gt;　我々の形式手法勉強会 &lt;a href="http://groups.google.co.jp/group/fm-forum"&gt;Formal Methods Forum&lt;/a&gt; も、名古屋の &lt;a href="http://coq.g.hatena.ne.jp/keyword/ProofCafe"&gt;ProofCafe&lt;/a&gt; と一緒に、昨年開催された &lt;a href="http://atnd.org/events/6022"&gt;Coq庵&lt;/a&gt; と同様の定理証明系イベントを開催したいと計画しています。&lt;br /&gt;&lt;br /&gt;　会場は新宿の豆蔵セミナールームを予定しています。（豆蔵様、会場提供ありがとうございます）&lt;br /&gt;&lt;br /&gt;　諸々決まりましたら、また報告します。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3087478357950901775?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3087478357950901775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3087478357950901775' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3087478357950901775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3087478357950901775'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/04/coqformal-methods-proof-assistant-day.html' title='[Coq][Formal Methods] Proof Assistant Day 2011 on 9/25(Sun)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5390144398996358802</id><published>2011-03-06T07:55:00.003+09:00</published><updated>2011-03-06T08:57:26.054+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Formal Methods Forum 2011/03/05</title><content type='html'>　昨日は&lt;a href="http://groups.google.com/group/fm-forum"&gt;Formal Methods Forum&lt;/a&gt;のミーティングが行われました。&lt;br /&gt;&lt;br /&gt;　昨年の年末から作っていた&lt;a href="http://portal.acm.org/citation.cfm?id=321249"&gt;Brzozowski'sの正規表現アルゴリズム&lt;/a&gt;（去年の年末にLtUで話題になった正規表現の微分を使った&lt;a href="http://arxiv.org/abs/1010.5023"&gt;Yacc is Dead&lt;/a&gt;のやつ）のCoqライブラリ化（実装が&lt;a href="http://www.cs.cornell.edu/courses/cs786/2004sp/Lectures/l02-axioms.pdf"&gt;Kleene代数の公理&lt;/a&gt;を満たす事を証明）が完成して&lt;a href="http://coq.inria.fr/pylons/contribs/view/RegExp/v8.3"&gt;CoqのUser contributionsに載った&lt;/a&gt;ので、その話をしました。（&lt;a href="http://www.slideshare.net/tmiya/regexp20110305-7162701"&gt;当日のプレゼン資料に一部加筆&lt;/a&gt;）&lt;br /&gt;&lt;br /&gt;　もうレポート提出期限も過ぎたので、&lt;a href="http://www.math.nagoya-u.ac.jp/~garrigue/lecture/2010_AW/index.html"&gt;今年のGarrigue先生の授業&lt;/a&gt;のレポート課題をみんなで解いてみよう、というのをしました。&lt;br /&gt;　私の証明はこんな感じ。最初の命題論理の証明は問題無かった様子。&lt;br /&gt;&lt;pre&gt;Section Coq1. &lt;br /&gt;Variables P Q R : Prop. &lt;br /&gt;Theorem and_compose : (P -&gt; Q) -&gt; (P -&gt; R) -&gt; P -&gt; Q /\ R. &lt;br /&gt;Proof.&lt;br /&gt;  intros pq pr p.&lt;br /&gt;  split.&lt;br /&gt;    apply (pq p).&lt;br /&gt;    apply (pr p).&lt;br /&gt;Qed.&lt;br /&gt;Theorem or_modus : P \/ (Q -&gt; R) -&gt; Q -&gt; P \/ R.&lt;br /&gt;Proof.&lt;br /&gt;  intros p_qr q.&lt;br /&gt;  destruct p_qr as [p|qr].&lt;br /&gt;    left.  apply p.&lt;br /&gt;    right.  apply (qr q).&lt;br /&gt;Qed.&lt;br /&gt;End Coq1.&lt;/pre&gt;&lt;br /&gt;次が append に関する性質で、これは解けた人が多かったです。&lt;br /&gt;&lt;pre&gt;Section Coq2. &lt;br /&gt;Require Import List. &lt;br /&gt;Variable A : Set.&lt;br /&gt;Fixpoint append (l1 l2 : list A) {struct l1} := &lt;br /&gt;match l1 with &lt;br /&gt;| nil =&gt; l2 &lt;br /&gt;| a :: l =&gt; a :: append l l2&lt;br /&gt;end.&lt;br /&gt;Theorem append_inv_head : forall l l1 l2 : list A, &lt;br /&gt;  append l l1 = append l l2 -&gt; l1 = l2.&lt;br /&gt;Proof.&lt;br /&gt;  induction l.&lt;br /&gt;    intros.  simpl in H.  auto.&lt;br /&gt;&lt;br /&gt;    intros.  simpl in H.  inversion H.&lt;br /&gt;    eapply IHl.  auto.&lt;br /&gt;Qed.&lt;/pre&gt;&lt;br /&gt;後半の問題は難しいみたいでした。私の解答は下記です。最初に幾つか補題を定義して目的の定理を証明しました、というのは嘘で、目的の定理を証明してる最中に欲しくなった補題を戻って証明しただけです。inversionが使えれば解ける問題だと思うので、やはりCoq初心者脱出の鍵はinversionを使える様になる、かと思う。&lt;br /&gt;&lt;pre&gt;Lemma append_nil : forall l, append l nil = l.&lt;br /&gt;Proof.&lt;br /&gt;  induction l; simpl; [|erewrite IHl]; auto.&lt;br /&gt;Qed.&lt;br /&gt;Lemma append_l1_a_l2 : forall a l1 l2,&lt;br /&gt;  append l1 (a::l2) = append (l1 ++ a::nil) l2.&lt;br /&gt;Proof.&lt;br /&gt;  induction l1; intros; simpl; [|erewrite IHl1]; auto.&lt;br /&gt;Qed.&lt;br /&gt;Lemma append_cons_not_nil : forall (a:A) l l', l ++ a::l' &lt;&gt; nil.&lt;br /&gt;Proof.&lt;br /&gt;  induction l; simpl; intros; intro; discriminate H.&lt;br /&gt;Qed.&lt;br /&gt;Lemma append_inv_a : forall (a:A) l1 l2,&lt;br /&gt;  l1 ++ a :: nil = l2 ++ a :: nil -&gt; l1 = l2.&lt;br /&gt;Proof.&lt;br /&gt;  induction l1; induction l2; simpl; intros. &lt;br /&gt;    (* l1 = nil, l2 = nil *)&lt;br /&gt;    auto.&lt;br /&gt;    (* l1 = nil, l2 = a0::l2 *)&lt;br /&gt;    inversion H.&lt;br /&gt;    specialize(append_cons_not_nil a0 l2 nil).  intros.&lt;br /&gt;    rewrite &lt;- H2 in H0.  elim H0.  auto.&lt;br /&gt;    (* l1 = a::l1, l2 = nil *)&lt;br /&gt;    inversion H.&lt;br /&gt;    specialize(append_cons_not_nil a l1 nil).  intros.&lt;br /&gt;    rewrite H2 in H0.  elim H0.  auto.&lt;br /&gt;    (* l1 = a::l1, l2 = a0::l2 *)&lt;br /&gt;    inversion H.&lt;br /&gt;    rewrite (IHl1 l2 H2).  auto.&lt;br /&gt;Qed.&lt;br /&gt;Theorem append_inv_tail : forall l l1 l2 : list A, &lt;br /&gt;  append l1 l = append l2 l -&gt; l1 = l2.&lt;br /&gt;Proof.&lt;br /&gt;  induction l; intros; simpl in H.&lt;br /&gt;    (* l = nil *)&lt;br /&gt;    repeat erewrite append_nil in H.  auto.&lt;br /&gt;    (* l = a::l *)&lt;br /&gt;    rewrite (append_l1_a_l2 a l1 l) in H.&lt;br /&gt;    rewrite (append_l1_a_l2 a l2 l) in H.&lt;br /&gt;    eapply (append_inv_a a).  eapply (IHl _ _ H).&lt;br /&gt;Qed.&lt;br /&gt;End Coq2.&lt;/pre&gt;&lt;br /&gt;revして前の定理に帰着せせる、という解答もありました。そっちは思いつかなかった。&lt;br /&gt;&lt;br /&gt;　あとは、&lt;a href="http://www.brucker.ch/projects/hol-ocl/"&gt;HOL-OCL&lt;/a&gt;というのがあるよ、とか。OCLってどの程度メジャーなんでしょうか。広く使われていて需要がありそうならIsabelleも勉強すべきかなぁ、とか。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5390144398996358802?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5390144398996358802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5390144398996358802' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5390144398996358802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5390144398996358802'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/03/coq-formal-methods-forum-20110305.html' title='[Coq] Formal Methods Forum 2011/03/05'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-1189807291432147178</id><published>2011-03-02T22:12:00.001+09:00</published><updated>2011-03-02T22:14:09.135+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TAPL'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] TAPL Chapter 8</title><content type='html'>TAPL Chap.8 の演習問題をCoqで証明しました。型があるのでChap.3より寧ろ楽かも。&lt;br /&gt;&lt;br /&gt;http://ideone.com/ttTKY&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1189807291432147178?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/1189807291432147178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=1189807291432147178' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1189807291432147178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1189807291432147178'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/03/coq-tapl-chapter-8.html' title='[Coq] TAPL Chapter 8'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5051326603347865662</id><published>2011-01-31T01:04:00.002+09:00</published><updated>2011-01-31T01:08:30.703+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Sample of Setoid</title><content type='html'>先日のFormal Methods Forumで話した&lt;a href="http://www.slideshare.net/tmiya/coq-setoid-20110129"&gt;setoidの話&lt;/a&gt;のCoqのコード。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Require Import Setoid.&lt;br /&gt;Require Import Relation_Definitions.&lt;br /&gt;Require Import Arith.&lt;br /&gt;Require Import Compare_dec.&lt;br /&gt;Require Import Omega.&lt;br /&gt;&lt;br /&gt;Section MyZ.&lt;br /&gt;&lt;br /&gt;(* 整数 Z' を構成するのに、nat * nat に同値関係 Z'eq を入れたものを用いる。&lt;br /&gt;  (a,b) in nat*nat に対し、a-b でZ'を作る、と考えてよい。 *)&lt;br /&gt;&lt;br /&gt;(* Z' のコンストラクタ *)&lt;br /&gt;Inductive Z' : Set :=&lt;br /&gt;| mkZ' : nat -&gt; nat -&gt; Z'.&lt;br /&gt;&lt;br /&gt;(* 同値関係 : (a,b) =Z= (c,d) iff a+d = b+c *)&lt;br /&gt;Definition Z'eq (z z':Z') : Prop :=&lt;br /&gt;  let (a,b) := z in&lt;br /&gt;  let (c,d) := z' in&lt;br /&gt;  a + d = b + c.&lt;br /&gt;&lt;br /&gt;Notation "a =Z= b" := (Z'eq a b) (at level 70).&lt;br /&gt;&lt;br /&gt;(* 後々の証明で使いやすい補題 *)&lt;br /&gt;Lemma Z'eq_inv : forall a b c d, (mkZ' a b) =Z= (mkZ' c d) -&gt;&lt;br /&gt;  {exists q, (a=c+q /\ b=d+q)} + {exists q, (a+q=c /\ b+q=d)}.&lt;br /&gt;Proof.&lt;br /&gt;  intros.  simpl in H.&lt;br /&gt;  destruct (le_lt_dec a c).&lt;br /&gt;    (* a &lt;= c *)&lt;br /&gt;    right.  exists (c - a).  omega.&lt;br /&gt;    (* c &lt; a *)&lt;br /&gt;    left.  exists (a - c).  omega.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;(* Z'eq が同値関係であることを証明する *)&lt;br /&gt;Print reflexive.&lt;br /&gt;Lemma Z'eq_refl : reflexive Z' Z'eq.&lt;br /&gt;Proof.&lt;br /&gt;  unfold reflexive.  intros.  destruct x.&lt;br /&gt;  unfold Z'eq.  omega.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Print symmetric.&lt;br /&gt;Lemma Z'eq_sym : symmetric Z' Z'eq.&lt;br /&gt;Proof.&lt;br /&gt;  unfold symmetric.  intros.  destruct x.  destruct y.&lt;br /&gt;  unfold Z'eq in *.  omega.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Print transitive.&lt;br /&gt;Lemma Z'eq_trans : transitive Z' Z'eq.&lt;br /&gt;Proof.&lt;br /&gt;  unfold transitive.  intros.  destruct x. destruct y. destruct z.&lt;br /&gt;  unfold Z'eq in *.  omega.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;(* Z'eq が同値関係であることが示せたので Setoid を構成する *)&lt;br /&gt;Add Parametric Relation : Z' Z'eq&lt;br /&gt;  reflexivity proved by Z'eq_refl&lt;br /&gt;  symmetry proved by Z'eq_sym&lt;br /&gt;  transitivity proved by Z'eq_trans&lt;br /&gt;  as Z'_rel.&lt;br /&gt;&lt;br /&gt;(* Z' 上の演算を定義する *)&lt;br /&gt;Definition Z'plus (z z':Z') : Z' :=&lt;br /&gt;  let (a,b) := z in&lt;br /&gt;  let (c,d) := z' in&lt;br /&gt;  mkZ' (a+c) (b+d).&lt;br /&gt;&lt;br /&gt;Add Parametric Morphism : Z'plus with&lt;br /&gt;  signature Z'eq ==&gt; Z'eq ==&gt; Z'eq as Z'_plus_mor.&lt;br /&gt;Proof.&lt;br /&gt;  (* Goal := x =Z= y -&gt; x0 =Z= y0 -&gt; Z'plus x x0 =Z= Z'plus y y0&lt;br /&gt;  Z'plus が well-defined であることを示す必要がある *)&lt;br /&gt;  intros.  destruct x; destruct y; destruct x0; destruct y0.&lt;br /&gt;  unfold Z'eq in *.  unfold Z'plus.  omega.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;(* 準備 *)&lt;br /&gt;Lemma Z'eq_plus_id_l : forall z a, Z'plus (mkZ' a a) z =Z= z.&lt;br /&gt;Proof.&lt;br /&gt;  intros.  destruct z.&lt;br /&gt;  unfold Z'plus; unfold Z'eq.  omega.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Lemma Z'eq_plus_comm : forall z z', Z'plus z z' =Z= Z'plus z' z.&lt;br /&gt;Proof.&lt;br /&gt;  intros.  destruct z; destruct z'.&lt;br /&gt;  unfold Z'plus; unfold Z'eq.  omega.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;(* setoid_rewrite を使ってみる例 *)&lt;br /&gt;Lemma Z'eq_plus_id_r : forall z a, Z'plus z (mkZ' a a) =Z= z. &lt;br /&gt;Proof.&lt;br /&gt;  intros.&lt;br /&gt;  setoid_rewrite (Z'eq_plus_comm z (mkZ' a a)).&lt;br /&gt;  apply Z'eq_plus_id_l.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;End MyZ.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5051326603347865662?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5051326603347865662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5051326603347865662' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5051326603347865662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5051326603347865662'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/01/coq-sample-of-setoid.html' title='[Coq] Sample of Setoid'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-853286504895078948</id><published>2011-01-10T01:23:00.002+09:00</published><updated>2011-01-10T02:05:03.299+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='7-Lang'/><title type='text'>[7-Lang][Ruby] Seven Languages in Seven Weeks : Ruby Day 1</title><content type='html'>　Bruce Tateの&lt;i&gt;Seven Languages in Seven Weeks&lt;/i&gt;を読み始めました。&lt;br /&gt;　最初の言語はRubyです。各言語をキャラクターに例えているのですが、Ruby = Merry Poppins らしい。&lt;br /&gt;　１日目の課題はこんな感じでOKなのかしらん。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; puts 'Hello, World!'&lt;br /&gt;Hello, World!&lt;br /&gt;=&gt; nil&lt;br /&gt;&gt;&gt; p "Hello, Ruby".index("Ruby")&lt;br /&gt;7&lt;br /&gt;=&gt; nil&lt;br /&gt;&gt;&gt; puts "@tmiya_\n"*10&lt;br /&gt;@tmiya_&lt;br /&gt;@tmiya_&lt;br /&gt;@tmiya_&lt;br /&gt;@tmiya_&lt;br /&gt;@tmiya_&lt;br /&gt;@tmiya_&lt;br /&gt;@tmiya_&lt;br /&gt;@tmiya_&lt;br /&gt;@tmiya_&lt;br /&gt;@tmiya_&lt;br /&gt;=&gt; nil&lt;br /&gt;&gt;&gt; (1..10).each {|n| puts "This is sentence number #{n}" }&lt;br /&gt;This is sentence number 1&lt;br /&gt;This is sentence number 2&lt;br /&gt;This is sentence number 3&lt;br /&gt;This is sentence number 4&lt;br /&gt;This is sentence number 5&lt;br /&gt;This is sentence number 6&lt;br /&gt;This is sentence number 7&lt;br /&gt;This is sentence number 8&lt;br /&gt;This is sentence number 9&lt;br /&gt;This is sentence number 10&lt;br /&gt;=&gt; 1..10&lt;br /&gt;&lt;br /&gt;% ruby numberGuess.rb&lt;br /&gt;5&lt;br /&gt;too large&lt;br /&gt;3&lt;br /&gt;too large&lt;br /&gt;1&lt;br /&gt;too small&lt;br /&gt;2&lt;br /&gt;correct!&lt;br /&gt;% cat numberGuess.rb&lt;br /&gt;randomNumber = rand(10)&lt;br /&gt;while ((guess = gets.to_i) != randomNumber)&lt;br /&gt;  if guess &lt; randomNumber then&lt;br /&gt;    puts "too small"&lt;br /&gt;  else&lt;br /&gt;    puts "too large"&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;puts "correct!"&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-853286504895078948?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/853286504895078948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=853286504895078948' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/853286504895078948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/853286504895078948'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/01/7-langruby-seven-languages-in-seven.html' title='[7-Lang][Ruby] Seven Languages in Seven Weeks : Ruby Day 1'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-6575389649312084149</id><published>2011-01-09T10:19:00.001+09:00</published><updated>2011-01-09T10:21:07.355+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>[Misc] Blog Design Changed</title><content type='html'>Blogのデザインをちょっといじってみました。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-6575389649312084149?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/6575389649312084149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=6575389649312084149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6575389649312084149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6575389649312084149'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/01/misc-blog-design-changed.html' title='[Misc] Blog Design Changed'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5931673081129025464</id><published>2011-01-09T09:30:00.004+09:00</published><updated>2011-01-09T09:49:19.693+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Memo'/><category scheme='http://www.blogger.com/atom/ns#' term='OmegaT'/><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><title type='text'>[Memo] How to translate LaTeX file with po4a + OmegaT</title><content type='html'>忘れない様に作業手順メモ&lt;br /&gt;&lt;a href="http://www.cbrc.jp/~tominaga/tips/osx_po4a_omegat.html"&gt;Mac OS X 10.5 で po4a と OmegaT で TeX 文書を翻訳&lt;/a&gt;を参考に。&lt;br /&gt;&lt;br /&gt;最初にファイルを作るのは&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;そもそもTutorial.v.texはTutorial.texからmake tutorialとかで作る。CoqのMakefile参照。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;~/usr/share/perl/po4a-0.41/po4a-gettextize -f latex -m Tutorial.v.tex -p Tutorial.v.pot&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;上記が通らない場合は po4a の LaTeX.pm, TeX.pm を無理に直したりする。po4a からは platex ではなく latex が呼ばれるのでスタイルも jsbook から book にしたり、フランス人の人名を ASCII の範囲にしたりなど最初に直す。&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;あとはOmegaTを使って翻訳。&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;~/coq/coq-8.2pl1/doc/tutorial/&lt;/code&gt;にあるCoq_TutorialというOmegaTプロジェクトを開いて翻訳する。一段落したら訳文ファイル生成。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;cd ~/coq/coq-8.2pl1/doc/tutorial/&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;cp Coq_Tutorial/target/Tutorial.v.pot ja.pot&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;~/usr/share/perl/po4a-0.41/po4a-translate -f latex -m Tutorial.v.tex -p ja.pot -l ja.tex&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;フォーマットを直す場合はbookじゃなくjsbookに直す。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;platex ja.tex ; platex ja.tex ; dvipdfmx ja.dvi&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5931673081129025464?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5931673081129025464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5931673081129025464' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5931673081129025464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5931673081129025464'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2011/01/memo-how-to-translate-latex-file-with.html' title='[Memo] How to translate LaTeX file with po4a + OmegaT'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-1633145886942730581</id><published>2010-12-24T22:56:00.003+09:00</published><updated>2010-12-24T23:03:04.621+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] How to Find Unreachable Nodes</title><content type='html'>&lt;a href="http://d.hatena.ne.jp/kencoba/20101224/1293158401"&gt;不正な状態遷移を見つけるアルゴリズム @ kencobaの日記&lt;/a&gt;経由。&lt;br /&gt;&lt;br /&gt;答えを出すだけならこんなのでもOK?　元の問題の規模が判らないが、この程度に小さな問題なら auto で探索出来る。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Axiom O A B C D E F G H I:Prop.&lt;br /&gt;Axiom OA : O -&gt; A.&lt;br /&gt;Axiom AB : A -&gt; B.&lt;br /&gt;Axiom BC : B -&gt; C.&lt;br /&gt;Axiom CB : C -&gt; B.&lt;br /&gt;Axiom CA : C -&gt; A.&lt;br /&gt;Axiom DB : D -&gt; B.&lt;br /&gt;Axiom DH : D -&gt; H.&lt;br /&gt;Axiom HD : D -&gt; H.&lt;br /&gt;Axiom EF : E -&gt; F.&lt;br /&gt;Axiom FG : F -&gt; G.&lt;br /&gt;Axiom GF : G -&gt; F.&lt;br /&gt;Axiom GE : G -&gt; E.&lt;br /&gt;Axiom II : I -&gt; I.&lt;br /&gt;&lt;br /&gt;Hint Resolve OA AB BC CB CA DB DH HD EF FG GF GE II.&lt;br /&gt;&lt;br /&gt;Goal O -&gt; A. info auto. Qed.&lt;br /&gt;Goal O -&gt; B. info auto. Qed.&lt;br /&gt;Goal O -&gt; C. info auto. Qed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Goal O -&gt; D.&lt;/code&gt;などはauto.で証明出来ないので、path が無いと判る。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1633145886942730581?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/1633145886942730581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=1633145886942730581' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1633145886942730581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1633145886942730581'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-how-to-find-unreachable-nodes.html' title='[Coq] How to Find Unreachable Nodes'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-1839794379456130417</id><published>2010-12-24T00:01:00.000+09:00</published><updated>2010-12-24T00:01:00.263+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : reflexivity (25 of 25)</title><content type='html'>　Coq でよく使われる tactic の紹介も今回で最後。最終回は reflexivity を紹介します。&lt;br /&gt;&lt;br /&gt;　reflexivity はゴールが等式で、左辺と右辺の値が等しい時に使います。内容的には apply refl_equal. と同じです。refl_equal はこんな公理。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Inductive eq (A : Type) (x : A) : A -&gt; Prop :=  refl_equal : x = x&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　左辺と右辺が全く同じ形をしていないと等式は成り立ちません（が、reflexivity は内部的に simpl を実行しているので simpl で簡単化して等しくなる物は成立します）。&lt;br /&gt;&lt;br /&gt;　ところで、同じ形というのはどこまで同じならば = が成り立つかというのは良く解らないので色々試してみました。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Definition f : nat -&gt; nat := fun x =&gt; x.&lt;br /&gt;Coq &lt; Definition h : nat -&gt; nat := fun y =&gt; y .&lt;br /&gt;Coq &lt; Goal f = h.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   f = h&lt;br /&gt;&lt;br /&gt;Unnamed_thm &lt; simpl.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   f = h&lt;br /&gt;&lt;br /&gt;Unnamed_thm &lt; unfold f.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   (fun x : nat =&gt; x) = h&lt;br /&gt;&lt;br /&gt;Unnamed_thm &lt; unfold h.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   (fun x : nat =&gt; x) = (fun y : nat =&gt; y)&lt;br /&gt;&lt;br /&gt;Unnamed_thm &lt; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Unnamed_thm &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　これを見ると、(fun x : nat =&gt; x) = (fun y : nat =&gt; y) は成立するようです。同様に、&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Goal forall P:nat-&gt;Prop, (forall n, P n) = (forall m, P m).&lt;br /&gt;Unnamed_thm0 &lt; intros P.&lt;br /&gt;Unnamed_thm0 &lt; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　これを見ると、(forall n : nat, P n) = (forall m : nat, P m) も成立。&lt;br /&gt;&lt;br /&gt;　上記の f, h の場合はreflexivityで等しい事が示せましたが、一般には関数が等しい事を reflexivity で証明する事は出来ません。　&lt;br /&gt;　f, g : nat -&gt; nat について、f = g ⇔ ∀n:nat, f n = g n.  を以て等しいとする場合は、こんな感じで証明します。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Definition f : nat -&gt; nat := fun x =&gt; x.&lt;br /&gt;&lt;br /&gt;Coq &lt; Fixpoint g(x:nat):nat :=&lt;br /&gt;Coq &lt; match x with&lt;br /&gt;Coq &lt; | O =&gt; O&lt;br /&gt;Coq &lt; | S n' =&gt; S (g n')&lt;br /&gt;Coq &lt; end.&lt;br /&gt;&lt;br /&gt;Coq &lt; Require Import Logic.FunctionalExtensionality.&lt;br /&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_reflexivity : f = g.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   f = g&lt;br /&gt;&lt;br /&gt;Sample_of_reflexivity &lt; extensionality n.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  ============================&lt;br /&gt;   f n = g n&lt;br /&gt;&lt;br /&gt;Sample_of_reflexivity &lt; unfold f.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  ============================&lt;br /&gt;   n = g n&lt;br /&gt;&lt;br /&gt;Sample_of_reflexivity &lt; induction n.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   0 = g 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; S n = g (S n)&lt;br /&gt;&lt;br /&gt;Sample_of_reflexivity &lt; reflexivity.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : n = g n&lt;br /&gt;  ============================&lt;br /&gt;   S n = g (S n)&lt;br /&gt;&lt;br /&gt;Sample_of_reflexivity &lt; simpl.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : n = g n&lt;br /&gt;  ============================&lt;br /&gt;   S n = S (g n)&lt;br /&gt;&lt;br /&gt;Sample_of_reflexivity &lt; rewrite &lt;- IHn.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : n = g n&lt;br /&gt;  ============================&lt;br /&gt;   S n = S n&lt;br /&gt;&lt;br /&gt;Sample_of_reflexivity &lt; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_reflexivity &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;　他にも、= を同値関係を以て定義する場合は Setoid というものを使って考える（Coqの型理論には集合論の商集合が無いので、代わりに = を同値関係で置き換えた物を使う）とか有るらしいのですが、そっちはちょっと調べきれませんでした。&lt;br /&gt;&lt;br /&gt;ーーーーー&lt;br /&gt;&lt;br /&gt;★後書き★&lt;br /&gt;&lt;br /&gt;　Coq Advent Calender を始めるにあたっては、&lt;a href="http://atnd.org/events/9238"&gt;Coq Party&lt;/a&gt;でのmaeda_さんの発表に有った「tactic使用例が有ると嬉しい」と「coqでの人気tactic」という話題からネタを頂きました。&lt;br /&gt;　25個もあると自分では使った事の無いtacticとかもあって結構使い方を調べたり、あるいは適当な証明課題を探したりなど、それなりに大変で、何度か挫けそうになりましたがなんとか最後まで書けて良かったです。&lt;br /&gt;　Coq を学ぶ人の参考になると良いなぁ。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1839794379456130417?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/1839794379456130417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=1839794379456130417' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1839794379456130417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1839794379456130417'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-reflexivity-25.html' title='[Coq] Coq Advent Calender : reflexivity (25 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-4015411058448160553</id><published>2010-12-23T09:38:00.002+09:00</published><updated>2010-12-23T09:44:12.658+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : exact (24 of 25)</title><content type='html'>　Coq でよく使われる tactic の24番目は exact です。&lt;br /&gt;&lt;br /&gt;　現在のゴールが、仮定のどれか、あるいは既存の定理にマッチする時に exact H?. とか exact my_theorem. とかするとゴールが証明されます。前者の場合は assumption. で済みますし、exact ではなく apply でもOKなんで、無理に使う必要は無いですが、ゴールと同じ物があったという意図を多少は示せるのかも。&lt;br /&gt;&lt;br /&gt;　exact を使って書いてみました。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_exact : forall n m, n + m = m + n.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall n m : nat, n + m = m + n&lt;br /&gt;&lt;br /&gt;Sample_of_exact &lt; intros.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   n + m = m + n&lt;br /&gt;&lt;br /&gt;Sample_of_exact &lt; induction n.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   0 + m = m + 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; S n + m = m + S n&lt;br /&gt;&lt;br /&gt;Sample_of_exact &lt; simpl.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   m = m + 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; S n + m = m + S n&lt;br /&gt;&lt;br /&gt;Sample_of_exact &lt; exact (plus_n_O m).&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  m : nat&lt;br /&gt;  IHn : n + m = m + n&lt;br /&gt;  ============================&lt;br /&gt;   S n + m = m + S n&lt;br /&gt;&lt;br /&gt;Sample_of_exact &lt; simpl.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  m : nat&lt;br /&gt;  IHn : n + m = m + n&lt;br /&gt;  ============================&lt;br /&gt;   S (n + m) = m + S n&lt;br /&gt;&lt;br /&gt;Sample_of_exact &lt; rewrite IHn. &lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  m : nat&lt;br /&gt;  IHn : n + m = m + n&lt;br /&gt;  ============================&lt;br /&gt;   S (m + n) = m + S n&lt;br /&gt;&lt;br /&gt;Sample_of_exact &lt; exact (plus_n_Sm m n).&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_exact &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-4015411058448160553?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/4015411058448160553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=4015411058448160553' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4015411058448160553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4015411058448160553'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-exact-24-of-25.html' title='[Coq] Coq Advent Calender : exact (24 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-726214783306352963</id><published>2010-12-22T23:35:00.003+09:00</published><updated>2010-12-22T23:42:15.121+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Link'/><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><title type='text'>[Link] Formal Methods Forum</title><content type='html'>　東京でほぼ毎月開催している形式手法の勉強会、Formal Methods Forum ですが、&lt;a href="https://groups.google.com/group/fm-forum?hl=ja"&gt;FMFのGoogle group&lt;/a&gt;に登録して頂くと開催案内や開催日程相談のメールが配信されます。&lt;br /&gt;　ATNDで告知しているのですが、Google groupに登録して頂いた方がより確実だと思います。&lt;br /&gt;&lt;br /&gt;　活動内容ですが11月分については&lt;a href="http://d.hatena.ne.jp/kencoba/20101205/1291557919"&gt;kencobaさんの日記&lt;/a&gt;なんかも参考にして頂けるといいかと。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-726214783306352963?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/726214783306352963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=726214783306352963' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/726214783306352963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/726214783306352963'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/link-formal-methods-forum.html' title='[Link] Formal Methods Forum'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-6602650903439550894</id><published>2010-12-22T00:01:00.000+09:00</published><updated>2010-12-22T00:01:00.640+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : specialize (23 of 25)</title><content type='html'>　Coq でよく使われる tactic の23番目は specialize です。&lt;br /&gt;&lt;br /&gt;　公理とかライブラリにある定理とか証明済み補題とかに特定の引数を適用した物を仮定に使いたい事があります。forall n, P n. みたいな補題Lのnに特定の値 n0 を代入した P n0 が仮定にあると良いなぁ、とか。&lt;br /&gt;　勿論、assert(H:P n0)とかcut (P n0)とか書いても良いのですが、specialize (L n0). と書けば cut (P n0)してapply (L n0) するのと同じになり、証明が短く判りやすくなります。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-replace-12-of.html"&gt;replaceの説明&lt;/a&gt;の時と同じ定理を、replaceを使わず、specializeとrewriteを使って証明してみます。証明の前提と成る公理は replace の回を参照して下さい。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Theorem inv_r : forall a:G, a * (inv a) = 1.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall a : G, a * inv a = 1&lt;br /&gt;&lt;br /&gt;inv_r &lt; intros.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   a * inv a = 1&lt;br /&gt;&lt;br /&gt;inv_r &lt; specialize (id_l (a * inv a)).&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   1 * (a * inv a) = a * inv a -&gt; a * inv a = 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;specializeすると、公理 id_l に (a * inv a) を適用した物が得られますので、intro して書き換えて消去します。あとは同様に。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;inv_r &lt; intro H; rewrite &lt;- H; clear H.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   1 * (a * inv a) = 1&lt;br /&gt;&lt;br /&gt;inv_r &lt; specialize (inv_l (inv a)); intro H; rewrite &lt;- H; clear H.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   inv (inv a) * inv a * (a * inv a) = inv (inv a) * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; specialize (assoc (inv (inv a)) (inv a) (a * inv a)); intro H; rewrite H; clear H.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   inv (inv a) * (inv a * (a * inv a)) = inv (inv a) * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; specialize (assoc (inv a) a (inv a)); intro H; rewrite &lt;- H; clear H.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   inv (inv a) * (inv a * a * inv a) = inv (inv a) * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; specialize (inv_l a); intro H; rewrite H; clear H.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   inv (inv a) * (1 * inv a) = inv (inv a) * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; specialize (id_l (inv a)); intro H; rewrite H; clear H.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   inv (inv a) * inv a = inv (inv a) * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;inv_r &lt; Qed.&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-6602650903439550894?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/6602650903439550894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=6602650903439550894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6602650903439550894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6602650903439550894'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-specialize-23.html' title='[Coq] Coq Advent Calender : specialize (23 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3316781300859401704</id><published>2010-12-21T04:35:00.003+09:00</published><updated>2010-12-21T05:17:24.780+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : left, right (21,22 of 25)</title><content type='html'>　Coqでよく使われる tactic の21,22番目は left と right です。&lt;br /&gt;　最初に25個と決めて、でもよく考えると12/24で終了すべき。都合が良いのでここで２つ紹介して帳尻を合わせます。&lt;br /&gt;&lt;br /&gt;　left は constructor 1 、right は constructor 2 の意味で、実は goal が A \/ B の場合に限らず、コンストラクタが２通りあってどちらかを明示的に指定したい時に使えます。&lt;br /&gt;　大抵そういう場合は左右と対応している訳ですが、例えば nat とかも left が O を指すはず。同様に n:nat に対して destruct n ではなく split とかも使えるはず。単に他人に判りにくいだけですが。&lt;br /&gt;&lt;br /&gt;　今回は sumbool について left, right を使う例です。やはり左右に対応しています。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_left_right : forall n:nat, {n = 0} + {n &lt;&gt; 0}.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall n : nat, {n = 0} + {n &lt;&gt; 0}&lt;br /&gt;&lt;br /&gt;Sample_of_left_right &lt; induction n.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   {0 = 0} + {0 &lt;&gt; 0}&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; {S n = 0} + {S n &lt;&gt; 0}&lt;br /&gt;&lt;br /&gt;Sample_of_left_right &lt; left.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   0 = 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; {S n = 0} + {S n &lt;&gt; 0}&lt;br /&gt;&lt;br /&gt;Sample_of_left_right &lt; reflexivity.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : {n = 0} + {n &lt;&gt; 0}&lt;br /&gt;  ============================&lt;br /&gt;   {S n = 0} + {S n &lt;&gt; 0}&lt;br /&gt;&lt;br /&gt;Sample_of_left_right &lt; right.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : {n = 0} + {n &lt;&gt; 0}&lt;br /&gt;  ============================&lt;br /&gt;   S n &lt;&gt; 0&lt;br /&gt;&lt;br /&gt;Sample_of_left_right &lt; intro.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : {n = 0} + {n &lt;&gt; 0}&lt;br /&gt;  H : S n = 0&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;Sample_of_left_right &lt; inversion H.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_left_right &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3316781300859401704?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3316781300859401704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3316781300859401704' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3316781300859401704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3316781300859401704'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-left-right-2122.html' title='[Coq] Coq Advent Calender : left, right (21,22 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5446599863512714868</id><published>2010-12-20T00:54:00.000+09:00</published><updated>2010-12-20T00:54:15.596+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : generalize (20 of 25)</title><content type='html'>　Coqでよく使われる tactic の20番目は generalize です。&lt;br /&gt;&lt;br /&gt;　generalize は intro の逆で、具体的な値の term を、"forall t" のような形に戻します。&lt;br /&gt;　簡単な使用例は下記の様なものです。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma sample_of_generalize : forall x y, 0 &lt;= x + y + y.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall x y : nat, 0 &lt;= x + y + y&lt;br /&gt;&lt;br /&gt;sample_of_generalize &lt; intros.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  x : nat&lt;br /&gt;  y : nat&lt;br /&gt;  ============================&lt;br /&gt;   0 &lt;= x + y + y&lt;br /&gt;&lt;br /&gt;sample_of_generalize &lt; generalize (x + y + y).&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  x : nat&lt;br /&gt;  y : nat&lt;br /&gt;  ============================&lt;br /&gt;   forall n : nat, 0 &lt;= n&lt;br /&gt;&lt;br /&gt;sample_of_generalize &lt; Require Import Arith.Le.&lt;br /&gt;&lt;br /&gt;sample_of_generalize &lt; apply le_O_n.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;sample_of_generalize &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;　単純に generalize で戻せない場合は、generalize dependent t のような形で使います。例えば下記の証明（TAPLの練習問題の証明）で使っています。よほど明らかな場合以外は、generalize dependentの形で使う事が多い様に思います。&lt;br /&gt;　まず証明の前提の定義を幾つか。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Inductive term : Set :=&lt;br /&gt;| TmTrue : term&lt;br /&gt;| TmFalse : term&lt;br /&gt;| TmIf : term -&gt; term -&gt; term -&gt; term&lt;br /&gt;| TmZero : term&lt;br /&gt;| TmSucc : term -&gt; term&lt;br /&gt;| TmPred : term -&gt; term&lt;br /&gt;| TmIszero : term -&gt; term.&lt;br /&gt;&lt;br /&gt;Inductive nvalue : term -&gt; Prop :=&lt;br /&gt;| NvZero : nvalue TmZero&lt;br /&gt;| NvSucc : forall t, nvalue t -&gt; nvalue (TmSucc t).&lt;br /&gt;&lt;br /&gt;Inductive bvalue : term -&gt; Prop :=&lt;br /&gt;| BvTrue : bvalue TmTrue&lt;br /&gt;| BvFalse : bvalue TmFalse.&lt;br /&gt;&lt;br /&gt;Definition value(t:term) : Prop := bvalue t \/ nvalue t.&lt;br /&gt;&lt;br /&gt;Inductive eval : term -&gt; term -&gt; Prop :=&lt;br /&gt;| EvIfTrue : forall t2 t3, eval (TmIf TmTrue t2 t3) t2&lt;br /&gt;| EvIfFalse : forall t2 t3, eval (TmIf TmFalse t2 t3) t3&lt;br /&gt;| EvIf : forall t1 t1' t2 t3, eval t1 t1' -&gt; eval (TmIf t1 t2 t3) (TmIf t1' t2 t3)&lt;br /&gt;| EvSucc : forall t1 t1', eval t1 t1' -&gt; eval (TmSucc t1) (TmSucc t1')&lt;br /&gt;| EvPred : forall t1 t1', eval t1 t1' -&gt; eval (TmPred t1) (TmPred t1')&lt;br /&gt;| EvPredZero : eval (TmPred TmZero) TmZero&lt;br /&gt;| EvPredSucc : forall nv, nvalue nv -&gt; eval (TmPred (TmSucc nv)) nv&lt;br /&gt;| EvIszeroZero : eval (TmIszero TmZero) TmTrue&lt;br /&gt;| EvIszeroSucc : forall nv, nvalue nv -&gt; eval (TmIszero (TmSucc nv)) TmFalse&lt;br /&gt;| EvIszero : forall t1 t1', eval t1 t1' -&gt; eval (TmIszero t1) (TmIszero t1').&lt;br /&gt;&lt;br /&gt;Notation "t1 --&gt; t2" := (eval t1 t2) (at level 80, no associativity).&lt;br /&gt;&lt;br /&gt;Definition normal_form (t : term) : Prop := ~ exists t', eval t t'.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　ここで下記の定理を証明します。intros を下記の様にすると予めdestructした形で intros 可能です。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma value_is_normal_form : forall v, value v -&gt; normal_form v.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall v : term, value v -&gt; normal_form v&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; intros v [bv|nv] [t vEt].&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  v : term&lt;br /&gt;  bv : bvalue v&lt;br /&gt;  t : term&lt;br /&gt;  vEt : v --&gt; t&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; False&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; destruct bv; inversion vEt.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  v : term&lt;br /&gt;  nv : nvalue v&lt;br /&gt;  t : term&lt;br /&gt;  vEt : v --&gt; t&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ここで t をgeneralize dependentします。（generalize t だと、forall t:term, にならずうまくいかない。）&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;value_is_normal_form &lt; generalize dependent t.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  v : term&lt;br /&gt;  nv : nvalue v&lt;br /&gt;  ============================&lt;br /&gt;   forall t : term, v --&gt; t -&gt; False&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; induction nv.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall t : term, TmZero --&gt; t -&gt; False&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; forall t0 : term, TmSucc t --&gt; t0 -&gt; False&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; intros t zEt.                &lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  t : term&lt;br /&gt;  zEt : TmZero --&gt; t&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; forall t0 : term, TmSucc t --&gt; t0 -&gt; False&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; inversion zEt.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  t : term&lt;br /&gt;  nv : nvalue t&lt;br /&gt;  IHnv : forall t0 : term, t --&gt; t0 -&gt; False&lt;br /&gt;  ============================&lt;br /&gt;   forall t0 : term, TmSucc t --&gt; t0 -&gt; False&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; intros t0 stEt0.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  t : term&lt;br /&gt;  nv : nvalue t&lt;br /&gt;  IHnv : forall t0 : term, t --&gt; t0 -&gt; False&lt;br /&gt;  t0 : term&lt;br /&gt;  stEt0 : TmSucc t --&gt; t0&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; inversion stEt0.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  t : term&lt;br /&gt;  nv : nvalue t&lt;br /&gt;  IHnv : forall t0 : term, t --&gt; t0 -&gt; False&lt;br /&gt;  t0 : term&lt;br /&gt;  stEt0 : TmSucc t --&gt; t0&lt;br /&gt;  t1 : term&lt;br /&gt;  t1' : term&lt;br /&gt;  H0 : t --&gt; t1'&lt;br /&gt;  H : t1 = t&lt;br /&gt;  H1 : TmSucc t1' = t0&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; elim (IHnv t1').&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  t : term&lt;br /&gt;  nv : nvalue t&lt;br /&gt;  IHnv : forall t0 : term, t --&gt; t0 -&gt; False&lt;br /&gt;  t0 : term&lt;br /&gt;  stEt0 : TmSucc t --&gt; t0&lt;br /&gt;  t1 : term&lt;br /&gt;  t1' : term&lt;br /&gt;  H0 : t --&gt; t1'&lt;br /&gt;  H : t1 = t&lt;br /&gt;  H1 : TmSucc t1' = t0&lt;br /&gt;  ============================&lt;br /&gt;   t --&gt; t1'&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; exact H0.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;value_is_normal_form &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5446599863512714868?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5446599863512714868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5446599863512714868' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5446599863512714868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5446599863512714868'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-generalize-20.html' title='[Coq] Coq Advent Calender : generalize (20 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8670131011901584504</id><published>2010-12-19T00:20:00.000+09:00</published><updated>2010-12-19T00:21:07.241+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : inversion (19 of 25)</title><content type='html'>　Coq でよく使われる tactic の19番目は inversion です。&lt;br /&gt;　inversion は仮定に対して帰納的な定義を適用し、その仮定が成立する為の前提を導き出すか、あるいはそもそもそのような前提が存在しない（＝仮定が間違っている）ので証明終了、を導いてくれます。ある種の証明では inversion を使うと証明が非常に簡単なのですが、中で何をしているのかは簡単には説明するのは難しいです。&lt;br /&gt;&lt;br /&gt;　inversionの使用例というと典型的にはこの関数を定義することになっています。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Inductive even : nat -&gt; Prop :=&lt;br /&gt;Coq &lt; | EvenO : even O&lt;br /&gt;Coq &lt; | EvenSS : forall n, even n -&gt; even (S (S n)).&lt;br /&gt;even is defined&lt;br /&gt;even_ind is defined&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;偶数である事を、上記の様に帰納的に定義します。&lt;br /&gt;&lt;br /&gt;　では３が偶数でない事を証明しましょう。こういう定理の証明の時にはinversionが有用です。今回はinversionの中で何をしているかみたいのでinfo inversionとして使っています。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_inversion : ~(even 3).&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   ~ even 3&lt;br /&gt;&lt;br /&gt;Sample_of_inversion &lt; intro.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  H : even 3&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;Sample_of_inversion &lt; info inversion H.&lt;br /&gt; == assert (H0:3 = 3 -&gt; False).&lt;br /&gt;    refine match H in (even n) return (n = 3 -&gt; False) with&lt;br /&gt;           | EvenO =&gt; _&lt;br /&gt;           | EvenSS x x0 =&gt; _ x x0&lt;br /&gt;           end.&lt;br /&gt;    intro H0; refine ((_:0 = 3 -&gt; False) H0); clear H0; &lt;br /&gt;    intro H0; cut False;[intro H1|idtac].&lt;br /&gt;    refine ((_:False -&gt; False) H1); clear H1; intro H1;&lt;br /&gt;       exact (False_ind False H1).&lt;br /&gt;    &lt;br /&gt;    exact (eq_ind 0&lt;br /&gt;             (fun e : nat =&gt; match e with&lt;br /&gt;                             | 0 =&gt; True&lt;br /&gt;                             | S _ =&gt; False&lt;br /&gt;                             end) I 3 H0).&lt;br /&gt;    &lt;br /&gt;    intro n; intro H0; intro H1; refine ((_:even n -&gt; False) H0); &lt;br /&gt;    clear H0; refine ((_:S (S n) = 3 -&gt; even n -&gt; False) H1); &lt;br /&gt;    clear H1; intro H1;&lt;br /&gt;       cut (n = 1);[intro H0|idtac].&lt;br /&gt;    refine ((_:n = 1 -&gt; even n -&gt; False) H0); clear H0; &lt;br /&gt;    intro H0;&lt;br /&gt;       refine (eq_ind 1 (fun n : nat =&gt; even n -&gt; False) _ n _).&lt;br /&gt;    clear H1; intro H1; dependent move H1 after H0.&lt;br /&gt;    &lt;br /&gt;    refine (sym_eq _);&lt;br /&gt;       exact H0.&lt;br /&gt;    &lt;br /&gt;    exact (f_equal&lt;br /&gt;             (fun e : nat =&gt;&lt;br /&gt;              match e with&lt;br /&gt;              | 0 =&gt; n&lt;br /&gt;              | 1 =&gt; n&lt;br /&gt;              | S (S n) =&gt; n&lt;br /&gt;              end) H1).&lt;br /&gt;    &lt;br /&gt;    refine (H0 _); change (3 = 3); exact (refl_equal 3).&lt;br /&gt;    &lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  H : even 3&lt;br /&gt;  n : nat&lt;br /&gt;  H1 : even 1&lt;br /&gt;  H0 : n = 1&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　&lt;code&gt;H: even 3&lt;/code&gt;の前提に&lt;code&gt;H1: even 1&lt;/code&gt;が前提である事が判りました。このH1について再度inversionを使います。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Sample_of_inversion &lt; info inversion H1.&lt;br /&gt; == assert (H2:1 = 1 -&gt; False).&lt;br /&gt;    refine match H1 in (even n) return (n = 1 -&gt; False) with&lt;br /&gt;           | EvenO =&gt; _&lt;br /&gt;           | EvenSS x x0 =&gt; _ x x0&lt;br /&gt;           end.&lt;br /&gt;    intro H2; refine ((_:0 = 1 -&gt; False) H2); clear H2; &lt;br /&gt;    intro H2; cut False;[intro H3|idtac].&lt;br /&gt;    refine ((_:False -&gt; False) H3); clear H3; intro H3;&lt;br /&gt;       exact (False_ind False H3).&lt;br /&gt;    &lt;br /&gt;    exact (eq_ind 0&lt;br /&gt;             (fun e : nat =&gt; match e with&lt;br /&gt;                             | 0 =&gt; True&lt;br /&gt;                             | S _ =&gt; False&lt;br /&gt;                             end) I 1 H2).&lt;br /&gt;    &lt;br /&gt;    intro n0; intro H2; intro H3; refine ((_:even n0 -&gt; False) H2); &lt;br /&gt;    clear H2; refine ((_:S (S n0) = 1 -&gt; even n0 -&gt; False) H3); &lt;br /&gt;    clear H3; intro H3;&lt;br /&gt;       cut False;[intro H2|idtac].&lt;br /&gt;    refine ((_:False -&gt; even n0 -&gt; False) H2); clear H2; &lt;br /&gt;    intro H2;&lt;br /&gt;       exact (False_ind (even n0 -&gt; False) H2).&lt;br /&gt;    &lt;br /&gt;    exact (eq_ind (S (S n0))&lt;br /&gt;             (fun e : nat =&gt;&lt;br /&gt;              match e with&lt;br /&gt;              | 0 =&gt; False&lt;br /&gt;              | 1 =&gt; False&lt;br /&gt;              | S (S _) =&gt; True&lt;br /&gt;              end) I 1 H3).&lt;br /&gt;    &lt;br /&gt;    refine (H2 _); change (1 = 1); exact (refl_equal 1).&lt;br /&gt;    &lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_inversion &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;H1を成立させる前提が無いので、証明完了になります。&lt;br /&gt;&lt;br /&gt;　あと、inversionが役に立つ例というとsmall-stepの決定性の証明とかです。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;Coq &lt; Inductive term : Set :=&lt;br /&gt;Coq &lt; | TmTrue : term&lt;br /&gt;Coq &lt; | TmFalse : term&lt;br /&gt;Coq &lt; | TmIf : term -&gt; term -&gt; term -&gt; term.&lt;br /&gt;term is defined&lt;br /&gt;term_rect is defined&lt;br /&gt;term_ind is defined&lt;br /&gt;term_rec is defined&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Coq &lt; Inductive eval : term -&gt; term -&gt; Prop :=&lt;br /&gt;Coq &lt; | EvIfTrue : forall t2 t3, eval (TmIf TmTrue t2 t3) t2 &lt;br /&gt;Coq &lt; | EvIfFalse : forall t2 t3, eval (TmIf TmFalse t2 t3) t3&lt;br /&gt;Coq &lt; | EvIf : forall t1 t1' t2 t3, eval t1 t1' -&gt;&lt;br /&gt;Coq &lt;     eval (TmIf t1 t2 t3) (TmIf t1' t2 t3).&lt;br /&gt;eval is defined&lt;br /&gt;eval_ind is defined&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;上記の様にsmall-stepの規則を定義して、下記を証明します。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Theorem eval_deterministic : forall t t' t'', (eval t t') -&gt; (eval t t'') -&gt; (t' = t'').&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall t t' t'' : term, eval t t' -&gt; eval t t'' -&gt; t' = t''&lt;br /&gt;&lt;br /&gt;eval_deterministic &lt; intros t t' t'' tEt' tEt''.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  t : term&lt;br /&gt;  t' : term&lt;br /&gt;  t'' : term&lt;br /&gt;  tEt' : eval t t'&lt;br /&gt;  tEt'' : eval t t''&lt;br /&gt;  ============================&lt;br /&gt;   t' = t''&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;まず tEt' について induction で場合分けをします。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;eval_deterministic &lt; induction tEt' as [t2 t3|t2 t3|t1 t1' t2 t3 t1Et1'] in t'', tEt'' |-*.&lt;br /&gt;3 subgoals&lt;br /&gt;  &lt;br /&gt;  t'' : term&lt;br /&gt;  t2 : term&lt;br /&gt;  t3 : term&lt;br /&gt;  tEt'' : eval (TmIf TmTrue t2 t3) t''&lt;br /&gt;  ============================&lt;br /&gt;   t2 = t''&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; t3 = t''&lt;br /&gt;subgoal 3 is:&lt;br /&gt; TmIf t1' t2 t3 = t''&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;最初の場合は、t' = TmIf TmTrue t2 t3 の場合です。ここで tEt'' については induction ではなくinversion を使うと、tEt'' が成立するような t'' の場合分けを自動で行ってくれます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;eval_deterministic &lt; inversion tEt'' as [t2_ t3_| t2_ t3_| t1_ t1'_ t2_ t3_ t1Et1'_].&lt;br /&gt;4 subgoals&lt;br /&gt;  &lt;br /&gt;  t'' : term&lt;br /&gt;  t2 : term&lt;br /&gt;  t3 : term&lt;br /&gt;  tEt'' : eval (TmIf TmTrue t2 t3) t''&lt;br /&gt;  t2_ : term&lt;br /&gt;  t3_ : term&lt;br /&gt;  H0 : t2_ = t2&lt;br /&gt;  H1 : t3_ = t3&lt;br /&gt;  H2 : t2 = t''&lt;br /&gt;  ============================&lt;br /&gt;   t'' = t''&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; t2 = TmIf t1'_ t2 t3&lt;br /&gt;subgoal 3 is:&lt;br /&gt; t3 = t''&lt;br /&gt;subgoal 4 is:&lt;br /&gt; TmIf t1' t2 t3 = t''&lt;br /&gt;&lt;br /&gt;eval_deterministic &lt; reflexivity.&lt;br /&gt;3 subgoals&lt;br /&gt;  &lt;br /&gt;  t'' : term&lt;br /&gt;  t2 : term&lt;br /&gt;  t3 : term&lt;br /&gt;  tEt'' : eval (TmIf TmTrue t2 t3) t''&lt;br /&gt;  t1_ : term&lt;br /&gt;  t1'_ : term&lt;br /&gt;  t2_ : term&lt;br /&gt;  t3_ : term&lt;br /&gt;  t1Et1'_ : eval TmTrue t1'_&lt;br /&gt;  H : t1_ = TmTrue&lt;br /&gt;  H1 : t2_ = t2&lt;br /&gt;  H2 : t3_ = t3&lt;br /&gt;  H0 : TmIf t1'_ t2 t3 = t''&lt;br /&gt;  ============================&lt;br /&gt;   t2 = TmIf t1'_ t2 t3&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; t3 = t''&lt;br /&gt;subgoal 3 is:&lt;br /&gt; TmIf t1' t2 t3 = t''&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　ここで&lt;code&gt;inversion t1Et1'_&lt;/code&gt;を行います。TmTrueが何かにevalされる規則はevalに無いので、仮定が不成立となり、goalの証明が終わります。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;eval_deterministic &lt; inversion t1Et1'_.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  t'' : term&lt;br /&gt;  t2 : term&lt;br /&gt;  t3 : term&lt;br /&gt;  tEt'' : eval (TmIf TmFalse t2 t3) t''&lt;br /&gt;  ============================&lt;br /&gt;   t3 = t''&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; TmIf t1' t2 t3 = t''&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　t' = TmIfFalse t2 t3 の場合は同様の証明をすればOKです。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;eval_deterministic &lt; inversion tEt'' as [t2_ t3_| t2_ t3_| t1_ t1'_ t2_ t3_ t1Et1'_].&lt;br /&gt;eval_deterministic &lt; reflexivity.&lt;br /&gt;eval_deterministic &lt; inversion t1Et1'_.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  t'' : term&lt;br /&gt;  t1 : term&lt;br /&gt;  t1' : term&lt;br /&gt;  t2 : term&lt;br /&gt;  t3 : term&lt;br /&gt;  t1Et1' : eval t1 t1'&lt;br /&gt;  tEt'' : eval (TmIf t1 t2 t3) t''&lt;br /&gt;  IHt1Et1' : eval t1 t'' -&gt; t1' = t''&lt;br /&gt;  ============================&lt;br /&gt;   TmIf t1' t2 t3 = t''&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　最後は、t' = TmIf t1 t2 t3 の場合についてです。やはりtEt''についてinversionします。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;eval_deterministic &lt; inversion tEt'' as [t2_ t3_| t2_ t3_| t1_ t1'_ t2_ t3_ t1Et1'_].&lt;br /&gt;3 subgoals&lt;br /&gt;  &lt;br /&gt;  t'' : term&lt;br /&gt;  t1 : term&lt;br /&gt;  t1' : term&lt;br /&gt;  t2 : term&lt;br /&gt;  t3 : term&lt;br /&gt;  t1Et1' : eval t1 t1'&lt;br /&gt;  tEt'' : eval (TmIf t1 t2 t3) t''&lt;br /&gt;  IHt1Et1' : eval t1 t'' -&gt; t1' = t''&lt;br /&gt;  t2_ : term&lt;br /&gt;  t3_ : term&lt;br /&gt;  H0 : TmTrue = t1&lt;br /&gt;  H1 : t2_ = t2&lt;br /&gt;  H2 : t3_ = t3&lt;br /&gt;  H3 : t2 = t''&lt;br /&gt;  ============================&lt;br /&gt;   TmIf t1' t'' t3 = t''&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; TmIf t1' t2 t'' = t''&lt;br /&gt;subgoal 3 is:&lt;br /&gt; TmIf t1' t2 t3 = TmIf t1'_ t2 t3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　ここでも、H0とt1Et1'から、eval TmTrue t1'を作ってinversionして仮定が成立しない事を使って証明します。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;eval_deterministic &lt; rewrite &lt;- H0 in t1Et1'.&lt;br /&gt;3 subgoals&lt;br /&gt;  &lt;br /&gt;  t'' : term&lt;br /&gt;  t1 : term&lt;br /&gt;  t1' : term&lt;br /&gt;  t2 : term&lt;br /&gt;  t3 : term&lt;br /&gt;  t1Et1' : eval TmTrue t1'&lt;br /&gt;  tEt'' : eval (TmIf t1 t2 t3) t''&lt;br /&gt;  IHt1Et1' : eval t1 t'' -&gt; t1' = t''&lt;br /&gt;  t2_ : term&lt;br /&gt;  t3_ : term&lt;br /&gt;  H0 : TmTrue = t1&lt;br /&gt;  H1 : t2_ = t2&lt;br /&gt;  H2 : t3_ = t3&lt;br /&gt;  H3 : t2 = t''&lt;br /&gt;  ============================&lt;br /&gt;   TmIf t1' t'' t3 = t''&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; TmIf t1' t2 t'' = t''&lt;br /&gt;subgoal 3 is:&lt;br /&gt; TmIf t1' t2 t3 = TmIf t1'_ t2 t3&lt;br /&gt;&lt;br /&gt;eval_deterministic &lt; inversion t1Et1'.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  t'' : term&lt;br /&gt;  t1 : term&lt;br /&gt;  t1' : term&lt;br /&gt;  t2 : term&lt;br /&gt;  t3 : term&lt;br /&gt;  t1Et1' : eval t1 t1'&lt;br /&gt;  tEt'' : eval (TmIf t1 t2 t3) t''&lt;br /&gt;  IHt1Et1' : eval t1 t'' -&gt; t1' = t''&lt;br /&gt;  t2_ : term&lt;br /&gt;  t3_ : term&lt;br /&gt;  H0 : TmFalse = t1&lt;br /&gt;  H1 : t2_ = t2&lt;br /&gt;  H2 : t3_ = t3&lt;br /&gt;  H3 : t3 = t''&lt;br /&gt;  ============================&lt;br /&gt;   TmIf t1' t2 t'' = t''&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; TmIf t1' t2 t3 = TmIf t1'_ t2 t3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　同様にして、TmFalse の場合も証明出来ます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;eval_deterministic &lt; rewrite &lt;- H0 in t1Et1'.&lt;br /&gt;eval_deterministic &lt; inversion t1Et1'.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  t'' : term&lt;br /&gt;  t1 : term&lt;br /&gt;  t1' : term&lt;br /&gt;  t2 : term&lt;br /&gt;  t3 : term&lt;br /&gt;  t1Et1' : eval t1 t1'&lt;br /&gt;  tEt'' : eval (TmIf t1 t2 t3) t''&lt;br /&gt;  IHt1Et1' : forall t'' : term, eval t1 t'' -&gt; t1' = t''&lt;br /&gt;  t1_ : term&lt;br /&gt;  t1'_ : term&lt;br /&gt;  t2_ : term&lt;br /&gt;  t3_ : term&lt;br /&gt;  t1Et1'_ : eval t1 t1'_&lt;br /&gt;  H0 : t1_ = t1&lt;br /&gt;  H1 : t2_ = t2&lt;br /&gt;  H2 : t3_ = t3&lt;br /&gt;  H3 : TmIf t1'_ t2 t3 = t''&lt;br /&gt;  ============================&lt;br /&gt;   TmIf t1' t2 t3 = TmIf t1'_ t2 t3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;最後はIHt1Et1'のt''をt1'_にして、t1Et1'_と組み合わせてゴールを導きます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;eval_deterministic &lt; rewrite (IHt1Et1' t1'_ t1Et1'_).&lt;br /&gt;eval_deterministic &lt; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;eval_deterministic &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8670131011901584504?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8670131011901584504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8670131011901584504' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8670131011901584504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8670131011901584504'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-inversion-19-of.html' title='[Coq] Coq Advent Calender : inversion (19 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7384753522704443996</id><published>2010-12-18T00:12:00.001+09:00</published><updated>2010-12-18T00:35:08.745+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : clear (18 of 25)</title><content type='html'>　Coq でよく使われる tactic の18番目は clear です...って使わないと思うけどなぁ。&lt;br /&gt;&lt;br /&gt;　&lt;code&gt;clear H&lt;/code&gt;とすると、仮定 H が消えます。下記の様な感じです。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_clear : forall A B C, (A-&gt;B-&gt;C)-&gt;(A-&gt;B)-&gt;A-&gt;C.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall A B C : Type, (A -&gt; B -&gt; C) -&gt; (A -&gt; B) -&gt; A -&gt; C&lt;br /&gt;&lt;br /&gt;Sample_of_clear &lt; intros A B C abc ab a.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Type&lt;br /&gt;  B : Type&lt;br /&gt;  C : Type&lt;br /&gt;  abc : A -&gt; B -&gt; C&lt;br /&gt;  ab : A -&gt; B&lt;br /&gt;  a : A&lt;br /&gt;  ============================&lt;br /&gt;   C&lt;br /&gt;&lt;br /&gt;Sample_of_clear &lt; apply abc; clear abc.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  A : Type&lt;br /&gt;  B : Type&lt;br /&gt;  C : Type&lt;br /&gt;  ab : A -&gt; B&lt;br /&gt;  a : A&lt;br /&gt;  ============================&lt;br /&gt;   A&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; B&lt;br /&gt;&lt;br /&gt;Sample_of_clear &lt; exact a.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Type&lt;br /&gt;  B : Type&lt;br /&gt;  C : Type&lt;br /&gt;  ab : A -&gt; B&lt;br /&gt;  a : A&lt;br /&gt;  ============================&lt;br /&gt;   B&lt;br /&gt;&lt;br /&gt;Sample_of_clear &lt; apply ab; clear ab.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Type&lt;br /&gt;  B : Type&lt;br /&gt;  C : Type&lt;br /&gt;  a : A&lt;br /&gt;  ============================&lt;br /&gt;   A&lt;br /&gt;&lt;br /&gt;Sample_of_clear &lt; exact a.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_clear &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　使い終わって不要になった仮定をclearで消すと多少見通しが良くなる事もありますが、あまり使わないのではないかなぁ。&lt;br /&gt;&lt;br /&gt;　むしろ、各種 tactic の中で内部的に使われる事が多い様な気がします。例えば下記の簡単な tactic の swap の中で使われています。apply して一回使った仮定は不要なので clear で消しているようです。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Ltac swap H := &lt;br /&gt;  idtac "swap is OBSOLETE: use contradict instead.";&lt;br /&gt;  intro; apply H; clear H.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　これを使った証明です。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_claer : forall P, ~~~P -&gt; ~P.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall P : Prop, ~ ~ ~ P -&gt; ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_claer &lt; intros.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  H : ~ ~ ~ P&lt;br /&gt;  ============================&lt;br /&gt;   ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_claer &lt; swap H.&lt;br /&gt;swap is OBSOLETE: use contradict instead.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  H0 : P&lt;br /&gt;  ============================&lt;br /&gt;   ~ ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_claer &lt; swap H.&lt;br /&gt;swap is OBSOLETE: use contradict instead.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  H0 : P&lt;br /&gt;  ============================&lt;br /&gt;   P&lt;br /&gt;&lt;br /&gt;Sample_of_claer &lt; exact H0.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_claer &lt; Qed.&lt;br /&gt;intros.&lt;br /&gt;swap H.&lt;br /&gt;swap ipattern:H.&lt;br /&gt;exact H0.&lt;br /&gt;&lt;br /&gt;Sample_of_claer is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7384753522704443996?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7384753522704443996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7384753522704443996' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7384753522704443996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7384753522704443996'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/advent-calender-clear-18-of-25.html' title='[Coq] Coq Advent Calender : clear (18 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3836926705497679867</id><published>2010-12-17T10:54:00.002+09:00</published><updated>2010-12-18T00:34:29.877+09:00</updated><title type='text'>[Coq] Coq Advent Calender : elim (17 of 25)</title><content type='html'>　Coq でよく使われる tactic の17番目は elim です。&lt;br /&gt;&lt;br /&gt;　elim はほとんど induction と同じ事が出来ます。例えばこんな感じ。帰納法の仮定を自分で intro する必要があるのが違います。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_elim : forall n, n + 0 = n.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall n : nat, n + 0 = n&lt;br /&gt;&lt;br /&gt;Sample_of_elim &lt; intros.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  ============================&lt;br /&gt;   n + 0 = n&lt;br /&gt;&lt;br /&gt;Sample_of_elim &lt; elim n.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  ============================&lt;br /&gt;   0 + 0 = 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; forall n0 : nat, n0 + 0 = n0 -&gt; S n0 + 0 = S n0&lt;br /&gt;&lt;br /&gt;Sample_of_elim &lt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;　ただこうやって帰納法で使うときはinductionする方が多い様にも思います。（golfだとelimが有利なのかな？）&lt;br /&gt;&lt;br /&gt;　下記の様にゴールが False で、仮定が ~P の形をしている時は、私は習慣で他のタクティックではなく elim を使います。こんな感じ。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_elim' : forall P, ~~(P \/ ~P).&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall P : Prop, ~ ~ (P \/ ~ P)&lt;br /&gt;&lt;br /&gt;Sample_of_elim' &lt; intros.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  ============================&lt;br /&gt;   ~ ~ (P \/ ~ P)&lt;br /&gt;&lt;br /&gt;Sample_of_elim' &lt; intro npnp.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  npnp : ~ (P \/ ~ P)&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;Sample_of_elim' &lt; elim npnp.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  npnp : ~ (P \/ ~ P)&lt;br /&gt;  ============================&lt;br /&gt;   P \/ ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_elim' &lt; right.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  npnp : ~ (P \/ ~ P)&lt;br /&gt;  ============================&lt;br /&gt;   ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_elim' &lt; intro p.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  npnp : ~ (P \/ ~ P)&lt;br /&gt;  p : P&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;Sample_of_elim' &lt; elim npnp.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  npnp : ~ (P \/ ~ P)&lt;br /&gt;  p : P&lt;br /&gt;  ============================&lt;br /&gt;   P \/ ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_elim' &lt; left.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  npnp : ~ (P \/ ~ P)&lt;br /&gt;  p : P&lt;br /&gt;  ============================&lt;br /&gt;   P&lt;br /&gt;&lt;br /&gt;Sample_of_elim' &lt; exact p.   &lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_elim' &lt; Qed.&lt;br /&gt;intros.&lt;br /&gt;intro npnp.&lt;br /&gt;elim npnp.&lt;br /&gt;right.&lt;br /&gt;intro p.&lt;br /&gt;elim npnp.&lt;br /&gt;left.&lt;br /&gt;exact p.&lt;br /&gt;&lt;br /&gt;Sample_of_elim' is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; &lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3836926705497679867?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3836926705497679867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3836926705497679867' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3836926705497679867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3836926705497679867'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-advent-calender-elim-17-of-25.html' title='[Coq] Coq Advent Calender : elim (17 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-719749497851395993</id><published>2010-12-16T01:39:00.000+09:00</published><updated>2010-12-16T01:40:10.742+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : ring (16 of 25)</title><content type='html'>　Coq でよく使われる tactic の16番目は ring です。&lt;br /&gt;&lt;br /&gt;　ring は可換な半環 ( 演算 +, * があって、それぞれ単位元 0, 1 があって、それぞれ交換則と結合則が成り立って、分配法則があってな数学的構造）での計算を行ってくれます。基本的には多項式の掛け算を展開し、標準形に直して比較するようなことをします。&lt;br /&gt;　使用するには&lt;code&gt;Require Import Ring.&lt;/code&gt;が必要です。&lt;br /&gt;&lt;br /&gt;　下記で色々試してみましたが、適宜 rewrite, replace なども併用しないとうまくいきませんでした。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Require Import ZArith Ring.&lt;br /&gt;&lt;br /&gt;Coq &lt; Open Scope Z_scope.&lt;br /&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_ring : forall a b:Z, a + b = 7 -&gt; a * b = 12 -&gt; a^2 + b^2 = 25.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall a b : Z, a + b = 7 -&gt; a * b = 12 -&gt; a ^ 2 + b ^ 2 = 25&lt;br /&gt;&lt;br /&gt;Sample_of_ring &lt; intros a b H1 H2.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : Z&lt;br /&gt;  b : Z&lt;br /&gt;  H1 : a + b = 7&lt;br /&gt;  H2 : a * b = 12&lt;br /&gt;  ============================&lt;br /&gt;   a ^ 2 + b ^ 2 = 25&lt;br /&gt;&lt;br /&gt;Sample_of_ring &lt; replace (a^2 + b^2) with ((a+b)^2 - 2*a*b) by ring.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : Z&lt;br /&gt;  b : Z&lt;br /&gt;  H1 : a + b = 7&lt;br /&gt;  H2 : a * b = 12&lt;br /&gt;  ============================&lt;br /&gt;   (a + b) ^ 2 - 2 * a * b = 25&lt;br /&gt;&lt;br /&gt;Sample_of_ring &lt; rewrite H1.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : Z&lt;br /&gt;  b : Z&lt;br /&gt;  H1 : a + b = 7&lt;br /&gt;  H2 : a * b = 12&lt;br /&gt;  ============================&lt;br /&gt;   7 ^ 2 - 2 * a * b = 25&lt;br /&gt;&lt;br /&gt;Sample_of_ring &lt; replace (2*a*b) with (2*12) by ring [H2].&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : Z&lt;br /&gt;  b : Z&lt;br /&gt;  H1 : a + b = 7&lt;br /&gt;  H2 : a * b = 12&lt;br /&gt;  ============================&lt;br /&gt;   7 ^ 2 - 2 * 12 = 25&lt;br /&gt;&lt;br /&gt;Sample_of_ring &lt; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_ring &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-719749497851395993?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/719749497851395993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=719749497851395993' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/719749497851395993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/719749497851395993'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-ring-16-of-25.html' title='[Coq] Coq Advent Calender : ring (16 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-178464181285824528</id><published>2010-12-15T02:06:00.000+09:00</published><updated>2010-12-15T02:06:11.547+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : case (15 of 25)</title><content type='html'>　Coq でよく使われる tactic の15番目は case です。&lt;br /&gt;&lt;br /&gt;　帰納的な型について自動で場合分けをしてくれるという意味では、13番目のinductionと同じですが、inductionと違って単に場合分けを行うだけで帰納法の仮定とかは作ってくれません。&lt;br /&gt;&lt;br /&gt;　今回は３値論理を定義してみます。帰納的な bool3 という型を定義し、それらに対する否定、論理積、論理和を定義します。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Inductive bool3 : Set := yes | maybe | no.&lt;br /&gt;bool3 is defined&lt;br /&gt;bool3_rect is defined&lt;br /&gt;bool3_ind is defined&lt;br /&gt;bool3_rec is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; Definition not3(b:bool3) :=&lt;br /&gt;Coq &lt;   match b with&lt;br /&gt;Coq &lt;   | yes =&gt; no&lt;br /&gt;Coq &lt;   | maybe =&gt; maybe&lt;br /&gt;Coq &lt;   | no =&gt; yes&lt;br /&gt;Coq &lt;   end.&lt;br /&gt;not3 is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; Definition and3(a b:bool3) :=&lt;br /&gt;Coq &lt;   match a,b with&lt;br /&gt;Coq &lt;   | yes,yes =&gt; yes&lt;br /&gt;Coq &lt;   | no, _ =&gt; no&lt;br /&gt;Coq &lt;   | _, no =&gt; no&lt;br /&gt;Coq &lt;   | _,_ =&gt; maybe&lt;br /&gt;Coq &lt;   end.&lt;br /&gt;and3 is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; Definition or3(a b:bool3) :=&lt;br /&gt;Coq &lt;   match a,b with&lt;br /&gt;Coq &lt;   | no,no =&gt; no&lt;br /&gt;Coq &lt;   | yes,_ =&gt; yes&lt;br /&gt;Coq &lt;   | _,yes =&gt; yes&lt;br /&gt;Coq &lt;   | _,_ =&gt; maybe&lt;br /&gt;Coq &lt;   end.&lt;br /&gt;or3 is defined&lt;br /&gt;&lt;br /&gt;Coq &lt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　では、bool3 における簡単な証明をしてみます。a, b についての場合分けを行うのに case タクティックを使用します。下記の例では case でゴールが増えるのを示したいので個別に case を使っていますが、普通は&lt;br /&gt;&lt;code&gt;case a; case b; reflexivity.&lt;/code&gt;&lt;br /&gt;で一行で９通りの場合分けを実施して終了とするでしょう。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_case : forall a b:bool3,&lt;br /&gt;Coq &lt;   not3 (or3 a b) = and3 (not3 a) (not3 b).&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall a b : bool3, not3 (or3 a b) = and3 (not3 a) (not3 b)&lt;br /&gt;&lt;br /&gt;Sample_of_case &lt; intros a b.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : bool3&lt;br /&gt;  b : bool3&lt;br /&gt;  ============================&lt;br /&gt;   not3 (or3 a b) = and3 (not3 a) (not3 b)&lt;br /&gt;&lt;br /&gt;Sample_of_case &lt; case a.&lt;br /&gt;3 subgoals&lt;br /&gt;  &lt;br /&gt;  a : bool3&lt;br /&gt;  b : bool3&lt;br /&gt;  ============================&lt;br /&gt;   not3 (or3 yes b) = and3 (not3 yes) (not3 b)&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; not3 (or3 maybe b) = and3 (not3 maybe) (not3 b)&lt;br /&gt;subgoal 3 is:&lt;br /&gt; not3 (or3 no b) = and3 (not3 no) (not3 b)&lt;br /&gt;&lt;br /&gt;Sample_of_case &lt; case b.&lt;br /&gt;5 subgoals&lt;br /&gt;  &lt;br /&gt;  a : bool3&lt;br /&gt;  b : bool3&lt;br /&gt;  ============================&lt;br /&gt;   not3 (or3 yes yes) = and3 (not3 yes) (not3 yes)&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; not3 (or3 yes maybe) = and3 (not3 yes) (not3 maybe)&lt;br /&gt;subgoal 3 is:&lt;br /&gt; not3 (or3 yes no) = and3 (not3 yes) (not3 no)&lt;br /&gt;subgoal 4 is:&lt;br /&gt; not3 (or3 maybe b) = and3 (not3 maybe) (not3 b)&lt;br /&gt;subgoal 5 is:&lt;br /&gt; not3 (or3 no b) = and3 (not3 no) (not3 b)&lt;br /&gt;&lt;br /&gt;Sample_of_case &lt; reflexivity.&lt;br /&gt;4 subgoals&lt;br /&gt;  &lt;br /&gt;  a : bool3&lt;br /&gt;  b : bool3&lt;br /&gt;  ============================&lt;br /&gt;   not3 (or3 yes maybe) = and3 (not3 yes) (not3 maybe)&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; not3 (or3 yes no) = and3 (not3 yes) (not3 no)&lt;br /&gt;subgoal 3 is:&lt;br /&gt; not3 (or3 maybe b) = and3 (not3 maybe) (not3 b)&lt;br /&gt;subgoal 4 is:&lt;br /&gt; not3 (or3 no b) = and3 (not3 no) (not3 b)&lt;br /&gt;&lt;br /&gt;Sample_of_case &lt; reflexivity.&lt;br /&gt;3 subgoals&lt;br /&gt;  &lt;br /&gt;  a : bool3&lt;br /&gt;  b : bool3&lt;br /&gt;  ============================&lt;br /&gt;   not3 (or3 yes no) = and3 (not3 yes) (not3 no)&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; not3 (or3 maybe b) = and3 (not3 maybe) (not3 b)&lt;br /&gt;subgoal 3 is:&lt;br /&gt; not3 (or3 no b) = and3 (not3 no) (not3 b)&lt;br /&gt;&lt;br /&gt;Sample_of_case &lt; reflexivity.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  a : bool3&lt;br /&gt;  b : bool3&lt;br /&gt;  ============================&lt;br /&gt;   not3 (or3 maybe b) = and3 (not3 maybe) (not3 b)&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; not3 (or3 no b) = and3 (not3 no) (not3 b)&lt;br /&gt;&lt;br /&gt;Sample_of_case &lt; case b; reflexivity.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : bool3&lt;br /&gt;  b : bool3&lt;br /&gt;  ============================&lt;br /&gt;   not3 (or3 no b) = and3 (not3 no) (not3 b)&lt;br /&gt;&lt;br /&gt;Sample_of_case &lt; case b; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_case &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-178464181285824528?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/178464181285824528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=178464181285824528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/178464181285824528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/178464181285824528'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-case-15-of-25.html' title='[Coq] Coq Advent Calender : case (15 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7879174324159886909</id><published>2010-12-14T04:24:00.001+09:00</published><updated>2010-12-14T22:19:36.600+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : split (14 of 25)</title><content type='html'>　Coq でよく使われる tactic の14番目は split です。...そんなに使うかなぁ？&lt;br /&gt;&lt;br /&gt;　split はゴールが &lt;code&gt;P /\ Q&lt;/code&gt; の形をしている時に、二つのゴール &lt;code&gt;P, Q&lt;/code&gt; に分割します。あとはそれぞれを別々に証明すればOKです。&lt;br /&gt;&lt;br /&gt;　簡単な例を下記に示します。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_split : forall A B C:Prop, A /\ (B /\ C) -&gt; (A /\ B) /\ C.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall A B C : Prop, A /\ B /\ C -&gt; (A /\ B) /\ C&lt;br /&gt;&lt;br /&gt;Sample_of_split &lt; intros A B C abc.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  abc : A /\ B /\ C&lt;br /&gt;  ============================&lt;br /&gt;   (A /\ B) /\ C&lt;br /&gt;&lt;br /&gt;Sample_of_split &lt; destruct abc as [a [b c]].&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  a : A&lt;br /&gt;  b : B&lt;br /&gt;  c : C&lt;br /&gt;  ============================&lt;br /&gt;   (A /\ B) /\ C&lt;br /&gt;&lt;br /&gt;Sample_of_split &lt; split.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  a : A&lt;br /&gt;  b : B&lt;br /&gt;  c : C&lt;br /&gt;  ============================&lt;br /&gt;   A /\ B&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; C&lt;br /&gt;&lt;br /&gt;Sample_of_split &lt; split.&lt;br /&gt;3 subgoals&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  a : A&lt;br /&gt;  b : B&lt;br /&gt;  c : C&lt;br /&gt;  ============================&lt;br /&gt;   A&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; B&lt;br /&gt;subgoal 3 is:&lt;br /&gt; C&lt;br /&gt;&lt;br /&gt;Sample_of_split &lt; assumption.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  a : A&lt;br /&gt;  b : B&lt;br /&gt;  c : C&lt;br /&gt;  ============================&lt;br /&gt;   B&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; C&lt;br /&gt;&lt;br /&gt;Sample_of_split &lt; assumption.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  a : A&lt;br /&gt;  b : B&lt;br /&gt;  c : C&lt;br /&gt;  ============================&lt;br /&gt;   C&lt;br /&gt;&lt;br /&gt;Sample_of_split &lt; assumption.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_split &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7879174324159886909?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7879174324159886909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7879174324159886909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7879174324159886909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7879174324159886909'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-advent-calender-split-14-of-25.html' title='[Coq] Coq Advent Calender : split (14 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7726321406806666513</id><published>2010-12-13T00:15:00.000+09:00</published><updated>2010-12-13T00:42:32.283+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : induction (13 of 25)</title><content type='html'>　Coq でよく使われる tactic の13番目は induction です。&lt;br /&gt;&lt;br /&gt;　Coq は帰納的な型を定義すると、その型に対する帰納法を自動で定義してくれます。例えば&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Inductive nat : Set :=  &lt;br /&gt;  O : nat &lt;br /&gt;| S : nat -&gt; nat&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;という自然数natに対して、&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;forall P : nat -&gt; Prop, &lt;br /&gt;  P 0 -&gt; &lt;br /&gt;  (forall n : nat, P n -&gt; P (S n)) -&gt; &lt;br /&gt;  forall n : nat, P n&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;というnat_indを定義してくれます。これを使って、自然数nについての帰納法の証明の時に、&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;n=0 の場合のゴール&lt;br /&gt;&lt;li&gt;nの時成り立つという仮定IHnと、S nの場合のゴール&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;を作ってくれます。同様にリストであれば、nilとconsの場合などです。&lt;br /&gt;&lt;br /&gt;　今までにも何度か induction を使った証明を示してきましたが、今回も簡単な例を。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma plus_comm : forall n m, n + m = m + n.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall n m : nat, n + m = m + n&lt;br /&gt;&lt;br /&gt;plus_comm &lt; induction n.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall m : nat, 0 + m = m + 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; forall m : nat, S n + m = m + S n&lt;br /&gt;&lt;br /&gt;plus_comm &lt; intro m.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   0 + m = m + 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; forall m : nat, S n + m = m + S n&lt;br /&gt;&lt;br /&gt;plus_comm &lt; simpl.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   m = m + 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; forall m : nat, S n + m = m + S n&lt;br /&gt;&lt;br /&gt;plus_comm &lt; erewrite &lt;- plus_n_O.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   m = m&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; forall m : nat, S n + m = m + S n&lt;br /&gt;&lt;br /&gt;plus_comm &lt; reflexivity.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : forall m : nat, n + m = m + n&lt;br /&gt;  ============================&lt;br /&gt;   forall m : nat, S n + m = m + S n&lt;br /&gt;&lt;br /&gt;plus_comm &lt; intro m.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : forall m : nat, n + m = m + n&lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   S n + m = m + S n&lt;br /&gt;&lt;br /&gt;plus_comm &lt; simpl.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : forall m : nat, n + m = m + n&lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   S (n + m) = m + S n&lt;br /&gt;&lt;br /&gt;plus_comm &lt; erewrite &lt;- plus_n_Sm.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : forall m : nat, n + m = m + n&lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   S (n + m) = S (m + n)&lt;br /&gt;&lt;br /&gt;plus_comm &lt; erewrite IHn.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : forall m : nat, n + m = m + n&lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   S (m + n) = S (m + n)&lt;br /&gt;&lt;br /&gt;plus_comm &lt; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;plus_comm &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7726321406806666513?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7726321406806666513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7726321406806666513' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7726321406806666513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7726321406806666513'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-induction-13-of.html' title='[Coq] Coq Advent Calender : induction (13 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8555996173966059343</id><published>2010-12-12T11:30:00.003+09:00</published><updated>2010-12-12T12:06:04.601+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : replace (12 of 25)</title><content type='html'>Coq でよく使われる tactic の12番目は replace です。&lt;br /&gt;&lt;br /&gt;　&lt;code&gt;replace t1 with t2&lt;/code&gt; とすると、t2 = t1 という等式をsubgoalに追加し、t2 = t1 を用いてゴールの書き換えを行います。書き換え規則 t2 = t1 の証明を先送りにすることで本筋の証明の見通しがよくなります。また、simpl, unfold, rewriteを使う場合とかで、「ゴールのこの部分だけ書き換えたいのだが別のところも書き換えられてしまう」と悩む場面もありますが、そういうときは replace でとりあえず部分的に書き換え、あとでその箇所の書き換えを証明すると楽です。&lt;br /&gt;&lt;br /&gt;　replace を多用するのは、等式変形を繰り返す場合です。今回はそういう例を。&lt;br /&gt;　下記の様に群 G を定義してみます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Axiom G : Set.  (* 群G *)&lt;br /&gt;Coq &lt; Axiom G_dec : forall a b:G, {a=b} + {a &lt;&gt; b}.  (* 単位元や逆元の一意性とかを示す時に必要 *)&lt;br /&gt;Coq &lt; Axiom mult : G -&gt; G -&gt; G.  (* 乗法 *)&lt;br /&gt;Coq &lt; Notation "a * b" := (mult a b).  (* 記号 * で書ける様にする *)&lt;br /&gt;Coq &lt; Axiom assoc : forall a b c:G, (a * b) * c = a * (b * c).  (* 結合則 *)&lt;br /&gt;Coq &lt; Axiom G1 : G.  (* 単位元 *)&lt;br /&gt;Coq &lt; Notation "1" := G1.  (* 記号 1 で書ける様にする *)&lt;br /&gt;Coq &lt; Axiom id_l : forall a:G, 1 * a = a.  (* 左単位元である *)&lt;br /&gt;Coq &lt; Axiom inv : G -&gt; G.  (* 逆元 *)&lt;br /&gt;Coq &lt; Axiom inv_l : forall a:G, (inv a) * a = 1.  (* 左逆元 *)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;　では、左逆元は右逆元でもあることを証明してみます。長くなるのでゴールを示すのは要所要所だけです。replaceを使うと、subgoalが増えているのが判ります。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Theorem inv_r : forall a:G, a * (inv a) = 1.&lt;br /&gt;inv_r &lt; intros.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   a * inv a = 1&lt;br /&gt;&lt;br /&gt;inv_r &lt; replace (a * inv a) with (1 * a * inv a).&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   1 * a * inv a = 1&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; 1 * a * inv a = a * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; replace (1 * a * inv a) with ((inv (inv a) * (inv a)) * a * inv a).&lt;br /&gt;3 subgoals&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   inv (inv a) * inv a * a * inv a = 1&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; inv (inv a) * inv a * a * inv a = 1 * a * inv a&lt;br /&gt;subgoal 3 is:&lt;br /&gt; 1 * a * inv a = a * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; replace (inv (inv a) * inv a * a * inv a) with (inv (inv a) * (inv a * a) * inv a).&lt;br /&gt;4 subgoals&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   inv (inv a) * (inv a * a) * inv a = 1&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; inv (inv a) * (inv a * a) * inv a = inv (inv a) * inv a * a * inv a&lt;br /&gt;subgoal 3 is:&lt;br /&gt; inv (inv a) * inv a * a * inv a = 1 * a * inv a&lt;br /&gt;subgoal 4 is:&lt;br /&gt; 1 * a * inv a = a * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; rewrite inv_l.  (* ここからは replace を使わなくても rewrite で簡単に変形出来る *)&lt;br /&gt;inv_r &lt; rewrite assoc.&lt;br /&gt;inv_r &lt; rewrite id_l.&lt;br /&gt;inv_r &lt; rewrite inv_l.&lt;br /&gt;4 subgoals&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   1 = 1&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; inv (inv a) * (inv a * a) * inv a = inv (inv a) * inv a * a * inv a&lt;br /&gt;subgoal 3 is:&lt;br /&gt; inv (inv a) * inv a * a * inv a = 1 * a * inv a&lt;br /&gt;subgoal 4 is:&lt;br /&gt; 1 * a * inv a = a * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; reflexivity.  (* メインゴールの証明完了。残りは replace の書き換えの証明 *)&lt;br /&gt;3 subgoals&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   inv (inv a) * (inv a * a) * inv a = inv (inv a) * inv a * a * inv a&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; inv (inv a) * inv a * a * inv a = 1 * a * inv a&lt;br /&gt;subgoal 3 is:&lt;br /&gt; 1 * a * inv a = a * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; rewrite &lt;- assoc; reflexivity.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   inv (inv a) * inv a * a * inv a = 1 * a * inv a&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; 1 * a * inv a = a * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; erewrite inv_l; reflexivity.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  a : G&lt;br /&gt;  ============================&lt;br /&gt;   1 * a * inv a = a * inv a&lt;br /&gt;&lt;br /&gt;inv_r &lt; rewrite assoc; rewrite id_l; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;inv_r &lt; Qed.&lt;br /&gt;intros.&lt;br /&gt;replace (a * inv a) with (1 * a * inv a) .&lt;br /&gt; replace (1 * a * inv a) with (inv (inv a) * inv a * a * inv a) .&lt;br /&gt;  replace (inv (inv a) * inv a * a * inv a) with&lt;br /&gt;   (inv (inv a) * (inv a * a) * inv a) .&lt;br /&gt;   rewrite inv_l in |- *.&lt;br /&gt;   rewrite assoc in |- *.&lt;br /&gt;   rewrite id_l in |- *.&lt;br /&gt;   rewrite inv_l in |- *.&lt;br /&gt;   reflexivity.&lt;br /&gt;   &lt;br /&gt;   rewrite &lt;- assoc in |- *; reflexivity.&lt;br /&gt;   &lt;br /&gt;  erewrite inv_l in |- *; reflexivity.&lt;br /&gt;  &lt;br /&gt; rewrite assoc in |- *; rewrite id_l in |- *; reflexivity.&lt;br /&gt; &lt;br /&gt;inv_r is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8555996173966059343?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8555996173966059343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8555996173966059343' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8555996173966059343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8555996173966059343'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-replace-12-of.html' title='[Coq] Coq Advent Calender : replace (12 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3547457819114587840</id><published>2010-12-11T03:54:00.003+09:00</published><updated>2010-12-11T04:07:49.397+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : exists (11 of 25)</title><content type='html'>　Coq でよく使われる tactic の11番目は exists です。&lt;br /&gt;　証明のゴールが exists x, P x とか { n:nat | isPrime n } とか、ある性質を満たす要素が存在することを求めている時に、「具体的に」その要素を与えてゴールを変形します。&lt;br /&gt;&lt;br /&gt;　下記は exists を使う簡単な例です。&lt;code&gt;m&lt;/code&gt;の具体的な値として&lt;code&gt;S n&lt;/code&gt; = n+1 を与えています。具体的なmを何か与えないとomegaでの自動証明は通りません。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Require Import Omega.&lt;br /&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_exists : forall n, exists m, n &lt; m.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall n : nat, exists m : nat, n &lt; m&lt;br /&gt;&lt;br /&gt;Sample_of_exists &lt; intros.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  ============================&lt;br /&gt;   exists m : nat, n &lt; m&lt;br /&gt;&lt;br /&gt;Sample_of_exists &lt; exists (S n).&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  ============================&lt;br /&gt;   n &lt; S n&lt;br /&gt;&lt;br /&gt;Sample_of_exists &lt; omega.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_exists &lt; Qed.&lt;br /&gt;intros.&lt;br /&gt;exists (S n).&lt;br /&gt;omega.&lt;br /&gt;&lt;br /&gt;Sample_of_exists is defined&lt;br /&gt;Coq &lt; &lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3547457819114587840?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3547457819114587840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3547457819114587840' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3547457819114587840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3547457819114587840'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-exists-11-of-25.html' title='[Coq] Coq Advent Calender : exists (11 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3028664101438152926</id><published>2010-12-10T13:31:00.003+09:00</published><updated>2010-12-10T13:38:57.784+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TAPL'/><category scheme='http://www.blogger.com/atom/ns#' term='OCaml'/><title type='text'>[TAPL][OCaml] Untyped Lambda Calculus Interpreter</title><content type='html'>　TAPLのChap.5を読むのに型無しλ計算のインタプリタが無いかなと探していたところ下記を見つけました。（...まぁそもそもそのくらい自分で作れよ、という話はあるんだが）&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cs.ru.nl/~freek/notes/lambda.ml"&gt;http://www.cs.ru.nl/~freek/notes/lambda.ml&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ページの内容を lambda.ml として保存し、&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ ocaml&lt;br /&gt;# #use "lambda.ml";;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;で読み込まれるので、あとは下記の様に試すだけ。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# nf "(^x.fx)a";;&lt;br /&gt;- : term = term "fa"&lt;br /&gt;# nf "(KISS)(KISS)";;&lt;br /&gt;- : term = term "^yzz'.zz'(yzz')"&lt;br /&gt;# red_gk all "SKK";;&lt;br /&gt;- : term list =&lt;br /&gt;[term "SKK"; term "(^yz.Kz(yz))K"; term "^z.(^y.z)(Kz)"; term "^z.z"]&lt;br /&gt;# red 7 "(^x.xx)(^x.xx)";;&lt;br /&gt;- : term list =&lt;br /&gt;[term "(^x.xx)^x.xx"; term "(^x.xx)^x.xx"; term "(^x.xx)^x.xx";&lt;br /&gt; term "(^x.xx)^x.xx"; term "(^x.xx)^x.xx"; term "(^x.xx)^x.xx";&lt;br /&gt; term "(^x.xx)^x.xx"; term "..."]&lt;br /&gt;#&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;手計算に自信が無い時に使うといいかなー。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3028664101438152926?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3028664101438152926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3028664101438152926' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3028664101438152926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3028664101438152926'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/taplocaml-untyped-lambda-calculus.html' title='[TAPL][OCaml] Untyped Lambda Calculus Interpreter'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-1662532043988285132</id><published>2010-12-10T01:06:00.003+09:00</published><updated>2010-12-10T01:30:42.499+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : unfold (10 of 25)</title><content type='html'>　Coq でよく使われる tactic の10番目は unfold です。unfold は関数定義を展開します。&lt;br /&gt;　unfold だけで使う場合も有りますが、fold と組み合わせて使う事もあります。fold は展開された関数を元に戻します。unfold して、simpl とか rewrite とかして、また fold して戻すと式が良い具合に変形されている場合があります。ここではそういう例を見てみましょう。&lt;br /&gt;&lt;br /&gt;　まず、&lt;code&gt;sum n := 1 + 2 + ... + n&lt;/code&gt;という関数を定義します。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Fixpoint sum n :=     &lt;br /&gt;Coq &lt;   match n with&lt;br /&gt;Coq &lt;   | O =&gt; O&lt;br /&gt;Coq &lt;   | S n' =&gt; S n' + sum n'&lt;br /&gt;Coq &lt;   end.&lt;br /&gt;sum is recursively defined (decreasing on 1st argument)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　次に、sum n = 1/2 * n * (n + 1) であることを証明したいのですが、割り算が入ると面倒ですから、次の定理を証明する事にします。今回は環に関する自動証明器の ring を使いたいのでArithとRingをImportしておきます。&lt;br /&gt;　nに関する帰納法で、n=0の場合はさらっと証明を流すことにします。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Require Import Arith Ring.                          &lt;br /&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_unfold : forall n, 2 * sum n = n * (n + 1).&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall n : nat, 2 * sum n = n * (n + 1)&lt;br /&gt;&lt;br /&gt;Sample_of_unfold &lt; induction n.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   2 * sum 0 = 0 * (0 + 1)&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; 2 * sum (S n) = S n * (S n + 1)&lt;br /&gt;&lt;br /&gt;Sample_of_unfold &lt; reflexivity.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : 2 * sum n = n * (n + 1)&lt;br /&gt;  ============================&lt;br /&gt;   2 * sum (S n) = S n * (S n + 1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　ここで、sum を unfold して、fold すると式が少し変形されます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Sample_of_unfold &lt; unfold sum.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : 2 * sum n = n * (n + 1)&lt;br /&gt;  ============================&lt;br /&gt;   2 *&lt;br /&gt;   (S n +&lt;br /&gt;    (fix sum (n0 : nat) : nat :=&lt;br /&gt;       match n0 with&lt;br /&gt;       | 0 =&gt; 0&lt;br /&gt;       | S n' =&gt; S n' + sum n'&lt;br /&gt;       end) n) = S n * (S n + 1)&lt;br /&gt;&lt;br /&gt;Sample_of_unfold &lt; fold sum.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : 2 * sum n = n * (n + 1)&lt;br /&gt;  ============================&lt;br /&gt;   2 * (S n + sum n) = S n * (S n + 1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　ここでreplaceを使ってちょっと左辺を書き換えます。書き換えて良い証明はsubgoal 2と後回しです。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;Sample_of_unfold &lt; replace (2 * (S n + sum n)) with (2 * S n + 2 * sum n).&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : 2 * sum n = n * (n + 1)&lt;br /&gt;  ============================&lt;br /&gt;   2 * S n + 2 * sum n = S n * (S n + 1)&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; 2 * S n + 2 * sum n = 2 * (S n + sum n)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　ここでIHnを用いて書き換えて式変形を ring で自動証明します。後回しにしたものもringで一発です。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;Sample_of_unfold &lt; rewrite IHn.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : 2 * sum n = n * (n + 1)&lt;br /&gt;  ============================&lt;br /&gt;   2 * S n + n * (n + 1) = S n * (S n + 1)&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; 2 * S n + 2 * sum n = 2 * (S n + sum n)&lt;br /&gt;&lt;br /&gt;Sample_of_unfold &lt; ring.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  IHn : 2 * sum n = n * (n + 1)&lt;br /&gt;  ============================&lt;br /&gt;   2 * S n + 2 * sum n = 2 * (S n + sum n)&lt;br /&gt;&lt;br /&gt;Sample_of_unfold &lt; ring.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_unfold &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1662532043988285132?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/1662532043988285132/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=1662532043988285132' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1662532043988285132'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1662532043988285132'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-unfold-10-of-25.html' title='[Coq] Coq Advent Calender : unfold (10 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3096948022250674545</id><published>2010-12-09T04:40:00.002+09:00</published><updated>2010-12-09T05:00:19.376+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : simpl (9 of 25)</title><content type='html'>　Coq でよく使われる tactic の９つ目は simpl です。simpl はβι簡約(beta, iota)をして式を簡単にします。βι簡約が何かについては&lt;a href="http://d.hatena.ne.jp/propella/20090215/p1"&gt;「言語ゲーム」の記事&lt;/a&gt;が判りやすいです。β簡約は関数適用で、ι簡約だと再帰的に関数が適用される、と考えると良いです。&lt;br /&gt;&lt;br /&gt;　予め、足し算の定義を示しておきます。plus を含んだ式を simpl すると、一つ目の変数 n について再帰的にパターンマッチして式を変形してくれます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Print plus.&lt;br /&gt;plus = &lt;br /&gt;fix plus (n m : nat) : nat := match n with&lt;br /&gt;                              | 0 =&gt; m&lt;br /&gt;                              | S p =&gt; S (plus p m)&lt;br /&gt;                              end&lt;br /&gt;     : nat -&gt; nat -&gt; nat&lt;br /&gt;&lt;br /&gt;Argument scopes are [nat_scope nat_scope]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　では足し算を使った simpl の使用例です。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_simpl : forall n m, n + m = m + n.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall n m : nat, n + m = m + n&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; intros n m.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   n + m = m + n&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; induction n.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   0 + m = m + 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; S n + m = m + S n&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; simpl.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   m = m + 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; S n + m = m + S n&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt; simpl を使うと左辺の&lt;code&gt;0 + m&lt;/code&gt;が&lt;code&gt;n&lt;/code&gt;に簡約されますが、右辺は変化がありません。ここは別途証明しておいた（というか標準ライブラリにはいっている）定理の&lt;code&gt;plus_n_O&lt;/code&gt;を使って書き換える事にします。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Sample_of_simpl &lt; Check plus_n_O.         &lt;br /&gt;plus_n_O&lt;br /&gt;     : forall n : nat, n = n + 0&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; erewrite &lt;- plus_n_O.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  m : nat&lt;br /&gt;  ============================&lt;br /&gt;   m = m&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; S n + m = m + S n&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; reflexivity.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  m : nat&lt;br /&gt;  IHn : n + m = m + n&lt;br /&gt;  ============================&lt;br /&gt;   S n + m = m + S n&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;帰納法の後半も simpl を使い、別の補題&lt;code&gt;plus_n_Sm&lt;/code&gt;を使います。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Sample_of_simpl &lt; simpl.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  m : nat&lt;br /&gt;  IHn : n + m = m + n&lt;br /&gt;  ============================&lt;br /&gt;   S (n + m) = m + S n&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; Check plus_n_Sm.&lt;br /&gt;plus_n_Sm&lt;br /&gt;     : forall n m : nat, S (n + m) = n + S m&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; erewrite &lt;- plus_n_Sm.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  m : nat&lt;br /&gt;  IHn : n + m = m + n&lt;br /&gt;  ============================&lt;br /&gt;   S (n + m) = S (m + n)&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; erewrite IHn.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  n : nat&lt;br /&gt;  m : nat&lt;br /&gt;  IHn : n + m = m + n&lt;br /&gt;  ============================&lt;br /&gt;   S (m + n) = S (m + n)&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_simpl &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3096948022250674545?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3096948022250674545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3096948022250674545' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3096948022250674545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3096948022250674545'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-simpl-9-of-25.html' title='[Coq] Coq Advent Calender : simpl (9 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7985607454236122038</id><published>2010-12-08T00:02:00.003+09:00</published><updated>2010-12-08T00:12:05.751+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : intro (8 of 25)</title><content type='html'>　Coq でよく使われる tactic の８つ目は intro です。基本的には&lt;a href="http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-intros-5-of-25.html"&gt;前に説明したintros&lt;/a&gt;と同じで、introsと違って一度に１つしかintro出来ないのが違います。&lt;br /&gt;　あと、introsと違ってintroの場合は、&lt;code&gt;~P&lt;/code&gt;の形のゴールを、&lt;code&gt;P&lt;/code&gt;という仮定と、&lt;code&gt;False&lt;/code&gt;というゴールに変形出来ます。&lt;code&gt;~P&lt;/code&gt;は&lt;code&gt;P-&gt;False&lt;/code&gt;なのですが、intros.では&lt;code&gt;~P&lt;/code&gt;は&lt;code&gt;~P&lt;/code&gt;のままです。&lt;br /&gt;&lt;br /&gt;　intro.を使った例です。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_intro : forall P, ~~~P -&gt; ~P.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall P : Prop, ~ ~ ~ P -&gt; ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_intro &lt; intro P.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  ============================&lt;br /&gt;   ~ ~ ~ P -&gt; ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_intro &lt; intro nnnp.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  nnnp : ~ ~ ~ P&lt;br /&gt;  ============================&lt;br /&gt;   ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_intro &lt; intro p.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  nnnp : ~ ~ ~ P&lt;br /&gt;  p : P&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;Sample_of_intro &lt; elim nnnp.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  nnnp : ~ ~ ~ P&lt;br /&gt;  p : P&lt;br /&gt;  ============================&lt;br /&gt;   ~ ~ P&lt;br /&gt;&lt;br /&gt;Sample_of_intro &lt; intro np.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  nnnp : ~ ~ ~ P&lt;br /&gt;  p : P&lt;br /&gt;  np : ~ P&lt;br /&gt;  ============================&lt;br /&gt;   False&lt;br /&gt;&lt;br /&gt;Sample_of_intro &lt; elim np.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  nnnp : ~ ~ ~ P&lt;br /&gt;  p : P&lt;br /&gt;  np : ~ P&lt;br /&gt;  ============================&lt;br /&gt;   P&lt;br /&gt;&lt;br /&gt;Sample_of_intro &lt; exact p.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_intro &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7985607454236122038?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7985607454236122038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7985607454236122038' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7985607454236122038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7985607454236122038'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-intro-8-of-25.html' title='[Coq] Coq Advent Calender : intro (8 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-4014543769396674555</id><published>2010-12-07T05:53:00.004+09:00</published><updated>2010-12-07T06:13:16.528+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : assert (7 of 25)</title><content type='html'>　Coq でよく使われる tactic の７つ目は assert です。&lt;br /&gt;&lt;br /&gt;　&lt;a href="http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-apply-1-of-25.html"&gt;１つ目のapply&lt;/a&gt;のところで書いた様に、Coqの証明は最初にゴールがあって、それを仮定と逆に戻して行く格好になっています。しかし証明する人間は仮定からゴールを考える方が楽な場合、つまり証明途中で適当な補題を作りたくなる場合があります。&lt;br /&gt;　補題はある程度汎用性があるならば、予め切り出して証明しておいた方が良いと思いますが、使い捨て的な補題は assert を使うと、証明内証明みたいに作る事ができます。例えば下記の例で、&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_assert : forall P Q, (P /\ P) -&gt; (Q /\ Q) -&gt; (P /\ Q). &lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall P Q : Prop, P /\ P -&gt; Q /\ Q -&gt; P /\ Q&lt;br /&gt;&lt;br /&gt;Sample_of_assert &lt; intros P Q pp qq.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  pp : P /\ P&lt;br /&gt;  qq : Q /\ Q&lt;br /&gt;  ============================&lt;br /&gt;   P /\ Q&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;　ここまで証明した段階で、&lt;code&gt;forall X, X /\ X -&gt; X&lt;/code&gt;という補題があれば、ppからPを、qqからQを取り出せて便利そうだと考えました。そこでassertを使います。すると現在の証明課題より先に、まずこの補題が証明課題になります。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Sample_of_assert &lt; assert(H: forall X, X /\ X -&gt; X).&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  pp : P /\ P&lt;br /&gt;  qq : Q /\ Q&lt;br /&gt;  ============================&lt;br /&gt;   forall X : Prop, X /\ X -&gt; X&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; P /\ Q&lt;br /&gt;&lt;br /&gt;Sample_of_assert &lt; intros X xx.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  pp : P /\ P&lt;br /&gt;  qq : Q /\ Q&lt;br /&gt;  X : Prop&lt;br /&gt;  xx : X /\ X&lt;br /&gt;  ============================&lt;br /&gt;   X&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; P /\ Q&lt;br /&gt;&lt;br /&gt;Sample_of_assert &lt; destruct xx as [x _].&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  pp : P /\ P&lt;br /&gt;  qq : Q /\ Q&lt;br /&gt;  X : Prop&lt;br /&gt;  x : X&lt;br /&gt;  ============================&lt;br /&gt;   X&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; P /\ Q&lt;br /&gt;&lt;br /&gt;Sample_of_assert &lt; exact x.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  pp : P /\ P&lt;br /&gt;  qq : Q /\ Q&lt;br /&gt;  H : forall X : Prop, X /\ X -&gt; X&lt;br /&gt;  ============================&lt;br /&gt;   P /\ Q&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　assertで設定した補題 H の証明が終わると、以後は仮定 H としてそれを使う事が出来ます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Sample_of_assert &lt; split.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  pp : P /\ P&lt;br /&gt;  qq : Q /\ Q&lt;br /&gt;  H : forall X : Prop, X /\ X -&gt; X&lt;br /&gt;  ============================&lt;br /&gt;   P&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; Q&lt;br /&gt;&lt;br /&gt;Sample_of_assert &lt; apply (H P).&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  pp : P /\ P&lt;br /&gt;  qq : Q /\ Q&lt;br /&gt;  H : forall X : Prop, X /\ X -&gt; X&lt;br /&gt;  ============================&lt;br /&gt;   P /\ P&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; Q&lt;br /&gt;&lt;br /&gt;Sample_of_assert &lt; exact pp. &lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  pp : P /\ P&lt;br /&gt;  qq : Q /\ Q&lt;br /&gt;  H : forall X : Prop, X /\ X -&gt; X&lt;br /&gt;  ============================&lt;br /&gt;   Q&lt;br /&gt;&lt;br /&gt;Sample_of_assert &lt; apply (H Q).&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  pp : P /\ P&lt;br /&gt;  qq : Q /\ Q&lt;br /&gt;  H : forall X : Prop, X /\ X -&gt; X&lt;br /&gt;  ============================&lt;br /&gt;   Q /\ Q&lt;br /&gt;&lt;br /&gt;Sample_of_assert &lt; exact qq.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_assert &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-4014543769396674555?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/4014543769396674555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=4014543769396674555' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4014543769396674555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4014543769396674555'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-assert-6-of-25.html' title='[Coq] Coq Advent Calender : assert (7 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-4931687891945103032</id><published>2010-12-06T10:06:00.003+09:00</published><updated>2010-12-06T10:23:19.456+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : omega (6 of 25)</title><content type='html'>　Coq でよく使われる tactic の６つ目は omega です...ってanarchy proofは課題が数学寄りに偏っているから、順序が６つ目というのはあまり気にしないで下さい。&lt;br /&gt;&lt;br /&gt;　omega タクティックはforallとかexistsとかを含まない形の&lt;a href="http://en.wikipedia.org/wiki/Presburger_arithmetic"&gt;Presburger算術 (Wikipedia)&lt;/a&gt;の式を自動証明してくれます。端的に言うと、&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;割り算無し&lt;/li&gt;&lt;br /&gt;&lt;li&gt;変数と変数の掛け算が入っているものはNG、変数と定数（2, 3などの具体的な整数）の掛け算はOK&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;みたいな感じの等式 or 不等式を証明します。&lt;br /&gt;　Coqがよく使われる理由は、この手の数式関係の自動証明が便利に使えるからだと思います。整数の等式不等式に関する公理定理を組み合わせて証明するとか大変ですからね。&lt;br /&gt;&lt;br /&gt;簡単な例はこんなのです。使い方は簡単で、Require Import Omega して、introsとかして、omega と入力するだけ。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Require Import Omega.&lt;br /&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_omega : forall x:nat, x &gt; 1 -&gt; 3 * x &gt; x + 2.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall x : nat, x &gt; 1 -&gt; 3 * x &gt; x + 2&lt;br /&gt;&lt;br /&gt;Sample_of_omega &lt; intros.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  x : nat&lt;br /&gt;  H : x &gt; 1&lt;br /&gt;  ============================&lt;br /&gt;   3 * x &gt; x + 2&lt;br /&gt;&lt;br /&gt;Sample_of_omega &lt; omega.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;　内部で実行された自動証明を見てみると、こんな感じらしい。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Sample_of_omega &lt; Undo.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  x : nat&lt;br /&gt;  H : x &gt; 1&lt;br /&gt;  ============================&lt;br /&gt;   3 * x &gt; x + 2&lt;br /&gt;&lt;br /&gt;Sample_of_omega &lt; info omega.&lt;br /&gt; == refine (Decidable.dec_not_not (3 * x &gt; x + 2) (dec_gt (3 * x) (x + 2)) _);&lt;br /&gt;       intro H0;&lt;br /&gt;       refine ((_:3 * x &lt;= x + 2 -&gt; False) (not_gt (3 * x) (x + 2) H0));&lt;br /&gt;       clear H0; intro H0;&lt;br /&gt;       refine ((_:(Z_of_nat x &gt; Z_of_nat 1)%Z -&gt; False) (inj_gt x 1 H));&lt;br /&gt;       change ((Z_of_nat x &gt; 1)%Z -&gt; False); clear H; &lt;br /&gt;    intro H;&lt;br /&gt;       refine ((_:(Z_of_nat (3 * x) &lt;= Z_of_nat (x + 2))%Z -&gt; False)&lt;br /&gt;                 (inj_le (3 * x) (x + 2) H0));&lt;br /&gt;       refine ((fun (P : Z -&gt; Prop) (H : P (Z_of_nat 3 * Z_of_nat x)%Z) =&gt;&lt;br /&gt;                eq_ind_r P H (inj_mult 3 x))&lt;br /&gt;                 (fun x0 : Z =&gt; (x0 &lt;= Z_of_nat (x + 2))%Z -&gt; False) _);&lt;br /&gt;       change ((3 * Z_of_nat x &lt;= Z_of_nat (x + 2))%Z -&gt; False);&lt;br /&gt;       refine ((fun (P : Z -&gt; Prop) (H : P (Z_of_nat x + Z_of_nat 2)%Z) =&gt;&lt;br /&gt;                eq_ind_r P H (inj_plus x 2))&lt;br /&gt;                 (fun x0 : Z =&gt; (3 * Z_of_nat x &lt;= x0)%Z -&gt; False) _);&lt;br /&gt;       change ((3 * Z_of_nat x &lt;= Z_of_nat x + 2)%Z -&gt; False); &lt;br /&gt;    clear H0; intro H0; refine (ex_ind _ (intro_Z x)); &lt;br /&gt;    intro Zvar2; intro Omega11; refine (and_ind _ Omega11); &lt;br /&gt;    clear Omega11; intro Omega8; intro Omega11;&lt;br /&gt;       refine ((_:(0 &lt;= Z_of_nat x + -1 + - (1))%Z -&gt; False)&lt;br /&gt;                 (Zgt_left (Z_of_nat x) 1 H)); clear H;&lt;br /&gt;       refine ((fun (P : Z -&gt; Prop) (H : P Zvar2) =&gt; eq_ind_r P H Omega8)&lt;br /&gt;                 (fun x : Z =&gt; (0 &lt;= x + -1 + - (1))%Z -&gt; False) _);&lt;br /&gt;       change ((0 &lt;= Zvar2 + -1 + -1)%Z -&gt; False);&lt;br /&gt;       refine (fast_Zplus_assoc_reverse Zvar2 (-1) &lt;br /&gt;                 (-1) (fun x : Z =&gt; (0 &lt;= x)%Z -&gt; False) _);&lt;br /&gt;       change ((0 &lt;= Zvar2 + -2)%Z -&gt; False);&lt;br /&gt;       refine (fast_Zred_factor0 Zvar2&lt;br /&gt;                 (fun x : Z =&gt; (0 &lt;= x + -2)%Z -&gt; False) _); &lt;br /&gt;    intro Omega10;&lt;br /&gt;       refine ((_:(0 &lt;= Z_of_nat x + 2 + - (3 * Z_of_nat x))%Z -&gt; False)&lt;br /&gt;                 (Zle_left (3 * Z_of_nat x) (Z_of_nat x + 2) H0)); &lt;br /&gt;    clear H0;&lt;br /&gt;       refine ((fun (P : Z -&gt; Prop) (H : P Zvar2) =&gt; eq_ind_r P H Omega8)&lt;br /&gt;                 (fun x0 : Z =&gt; (0 &lt;= x0 + 2 + - (3 * Z_of_nat x))%Z -&gt; False)&lt;br /&gt;                 _);&lt;br /&gt;       refine ((fun (P : Z -&gt; Prop) (H : P Zvar2) =&gt; eq_ind_r P H Omega8)&lt;br /&gt;                 (fun x : Z =&gt; (0 &lt;= Zvar2 + 2 + - (3 * x))%Z -&gt; False) _);&lt;br /&gt;       refine (fast_Zmult_comm 3 Zvar2&lt;br /&gt;                 (fun x : Z =&gt; (0 &lt;= Zvar2 + 2 + - x)%Z -&gt; False) _);&lt;br /&gt;       refine (fast_Zopp_mult_distr_r Zvar2 3&lt;br /&gt;                 (fun x : Z =&gt; (0 &lt;= Zvar2 + 2 + x)%Z -&gt; False) _);&lt;br /&gt;       change ((0 &lt;= Zvar2 + 2 + Zvar2 * -3)%Z -&gt; False);&lt;br /&gt;       refine (fast_Zplus_comm (Zvar2 + 2) (Zvar2 * -3)&lt;br /&gt;                 (fun x : Z =&gt; (0 &lt;= x)%Z -&gt; False) _);&lt;br /&gt;       refine (fast_Zplus_assoc (Zvar2 * -3) Zvar2 2&lt;br /&gt;                 (fun x : Z =&gt; (0 &lt;= x)%Z -&gt; False) _);&lt;br /&gt;       refine (fast_Zred_factor3 Zvar2 (-3)&lt;br /&gt;                 (fun x : Z =&gt; (0 &lt;= x + 2)%Z -&gt; False) _);&lt;br /&gt;       change ((0 &lt;= Zvar2 * Zneg (3 - 1) + 2)%Z -&gt; False); &lt;br /&gt;    intro Omega9;&lt;br /&gt;       cut ((Zvar2 * -2 + 2)%Z = ((Zvar2 * -1 + 1) * 2 + 0)%Z);[intro H|idtac].&lt;br /&gt;    refine ((_:(Zvar2 * -2 + 2)%Z = ((Zvar2 * -1 + 1) * 2 + 0)%Z -&gt; False) H);&lt;br /&gt;       clear H; intro auxiliary;&lt;br /&gt;       refine ((_:(0 &lt;= (Zvar2 * -1 + 1) * 2 + 0)%Z -&gt; False)&lt;br /&gt;                 (OMEGA1 (Zvar2 * -2 + 2) ((Zvar2 * -1 + 1) * 2 + 0)&lt;br /&gt;                    auxiliary Omega9)); clear auxiliary Omega9; &lt;br /&gt;    intro Omega9;&lt;br /&gt;       cut (2 &gt; 0)%Z;[intro H|idtac].&lt;br /&gt;    refine ((_:(2 &gt; 0)%Z -&gt; False) H); clear H;&lt;br /&gt;       cut (2 &gt; 0)%Z;[intro H|idtac].&lt;br /&gt;    refine ((_:(2 &gt; 0)%Z -&gt; (2 &gt; 0)%Z -&gt; False) H); &lt;br /&gt;    clear H; intro auxiliary_1; intro auxiliary_2;&lt;br /&gt;       refine ((_:(0 &lt;= Zvar2 * -1 + 1)%Z -&gt; False)&lt;br /&gt;                 (Zmult_le_approx 2 (Zvar2 * -1 + 1) 0 auxiliary_1&lt;br /&gt;                    auxiliary_2 Omega9));&lt;br /&gt;       clear auxiliary_1 auxiliary_2 Omega9; intro Omega9;&lt;br /&gt;       refine ((_:(0 &lt;= Zvar2 * 1 + -2 + (Zvar2 * -1 + 1))%Z -&gt; False)&lt;br /&gt;                 (OMEGA2 (Zvar2 * 1 + -2) (Zvar2 * -1 + 1) Omega10 Omega9));&lt;br /&gt;       refine (fast_OMEGA13 Zvar2 (-2) 1 1 (fun x : Z =&gt; (0 &lt;= x)%Z -&gt; False)&lt;br /&gt;                 _); change ((0 &lt;= Zneg (2 - 1))%Z -&gt; False);&lt;br /&gt;       change ((0 ?= Zneg (2 - 1))%Z &lt;&gt; Gt -&gt; False);&lt;br /&gt;       change (Gt &lt;&gt; Gt -&gt; False); intro H; refine (False_ind False _);&lt;br /&gt;       cut (Gt = Gt);[intro H0|idtac].&lt;br /&gt;    refine ((_:Gt = Gt -&gt; False) H0); clear H0;&lt;br /&gt;       cut (Gt &lt;&gt; Gt);[intro H0|idtac].&lt;br /&gt;    refine ((_:Gt &lt;&gt; Gt -&gt; Gt = Gt -&gt; False) H0); clear H0; &lt;br /&gt;    intro H0; intro H1; exact (H0 H1).&lt;br /&gt;    &lt;br /&gt;    exact H.&lt;br /&gt;    &lt;br /&gt;    change (Gt = Gt); exact (refl_equal Gt).&lt;br /&gt;    &lt;br /&gt;    change ((2 ?= 0)%Z = Gt); change (Gt = Gt); change (Gt = Gt);&lt;br /&gt;       exact (refl_equal Gt).&lt;br /&gt;    &lt;br /&gt;    change ((2 ?= 0)%Z = Gt); change (Gt = Gt); change (Gt = Gt);&lt;br /&gt;       exact (refl_equal Gt).&lt;br /&gt;    &lt;br /&gt;    refine (fast_OMEGA11 Zvar2 (-1) 1 0 2&lt;br /&gt;              (fun x : Z =&gt; (Zvar2 * -2 + 2)%Z = x) _);&lt;br /&gt;       change ((Zvar2 * -2 + 2)%Z = (Zvar2 * -2 + 2)%Z);&lt;br /&gt;       change ((Zvar2 * -2 + 2)%Z = (Zvar2 * -2 + 2)%Z);&lt;br /&gt;       exact (refl_equal (Zvar2 * -2 + 2)%Z).&lt;br /&gt;    &lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_omega &lt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-4931687891945103032?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/4931687891945103032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=4931687891945103032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4931687891945103032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4931687891945103032'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-omega-6-of-25.html' title='[Coq] Coq Advent Calender : omega (6 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-4067356245116572109</id><published>2010-12-05T07:11:00.000+09:00</published><updated>2010-12-05T07:11:10.733+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : intros (5 of 25)</title><content type='html'>　Coq でよく使われる tactic の５つ目は intros です。&lt;br /&gt;&lt;br /&gt;　実は過去４回の記事でも毎回 intros を使用していました。forall とかで定義された変数や -&gt; の左の式とかを仮定に持って行く為に使います。&lt;code&gt;intro&lt;/code&gt;の複数形なので、&lt;code&gt;intro&lt;/code&gt;を必要な回数繰り返してもOKです。&lt;br /&gt;　&lt;code&gt;intros.&lt;/code&gt; だけでも勝手に適当に名前（仮定は通常 H? みたいな名前）を付けてくれますが、判りやすさを考えると自分で適切な名前を付けた方が良いと思います。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_intros : forall A B C:Prop, (A-&gt;B-&gt;C) -&gt; (A-&gt;B) -&gt; A -&gt; C.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall A B C : Prop, (A -&gt; B -&gt; C) -&gt; (A -&gt; B) -&gt; A -&gt; C&lt;br /&gt;&lt;br /&gt;Sample_of_intros &lt; intros A B C abc ab a.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  abc : A -&gt; B -&gt; C&lt;br /&gt;  ab : A -&gt; B&lt;br /&gt;  a : A&lt;br /&gt;  ============================&lt;br /&gt;   C&lt;br /&gt;&lt;br /&gt;Sample_of_intros &lt; apply abc.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  abc : A -&gt; B -&gt; C&lt;br /&gt;  ab : A -&gt; B&lt;br /&gt;  a : A&lt;br /&gt;  ============================&lt;br /&gt;   A&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; B&lt;br /&gt;&lt;br /&gt;Sample_of_intros &lt; exact a.   &lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  abc : A -&gt; B -&gt; C&lt;br /&gt;  ab : A -&gt; B&lt;br /&gt;  a : A&lt;br /&gt;  ============================&lt;br /&gt;   B&lt;br /&gt;&lt;br /&gt;Sample_of_intros &lt; apply ab; exact a.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_intros &lt; Qed.&lt;br /&gt;intros A B C abc ab a.&lt;br /&gt;apply abc.&lt;br /&gt; exact a.&lt;br /&gt; &lt;br /&gt; apply ab; exact a.&lt;br /&gt; &lt;br /&gt;Sample_of_intros is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-4067356245116572109?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/4067356245116572109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=4067356245116572109' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4067356245116572109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4067356245116572109'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-intros-5-of-25.html' title='[Coq] Coq Advent Calender : intros (5 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3820568086545926465</id><published>2010-12-04T06:51:00.002+09:00</published><updated>2010-12-04T07:03:35.113+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : destruct (4 of 25)</title><content type='html'>　Coq でよく使われる tactic の４つ目は destruct です。&lt;br /&gt;&lt;br /&gt;　destruct は基本的にはある項を場合分けする時使うのですが、仮定の中にある /\ とか \/ とか exists とかを分解するのに使うのに便利です。（それ以外のときは induction とか case_eq とか使う事が多い様にも思います。）&lt;br /&gt;　下記の例では仮定 abc を分解して仮定 a, b, c を作っています。　&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_destruct : forall A B C:Prop,&lt;br /&gt;Coq &lt; A /\ (B /\ C) -&gt; (A /\ B) /\ C.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall A B C : Prop, A /\ B /\ C -&gt; (A /\ B) /\ C&lt;br /&gt;&lt;br /&gt;Sample_of_destruct &lt; intros A B C abc.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  abc : A /\ B /\ C&lt;br /&gt;  ============================&lt;br /&gt;   (A /\ B) /\ C&lt;br /&gt;&lt;br /&gt;Sample_of_destruct &lt; destruct abc as [a [b c]].&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Prop&lt;br /&gt;  B : Prop&lt;br /&gt;  C : Prop&lt;br /&gt;  a : A&lt;br /&gt;  b : B&lt;br /&gt;  c : C&lt;br /&gt;  ============================&lt;br /&gt;   (A /\ B) /\ C&lt;br /&gt;&lt;br /&gt;Sample_of_destruct &lt; split; [split|]; assumption.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_destruct &lt; Qed.&lt;br /&gt;intros A B C abc.&lt;br /&gt;destruct abc as (a, (b, c)).&lt;br /&gt;split; [ split | idtac ]; assumption.&lt;br /&gt;&lt;br /&gt;Sample_of_destruct is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3820568086545926465?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3820568086545926465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3820568086545926465' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3820568086545926465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3820568086545926465'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-destruct-4-of.html' title='[Coq] Coq Advent Calender : destruct (4 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7423820751170054446</id><published>2010-12-04T06:37:00.002+09:00</published><updated>2010-12-04T06:51:03.737+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : rewrite (3 of 25)</title><content type='html'>　Coq でよく使われる tactic の３つ目は rewrite です。&lt;br /&gt;&lt;br /&gt;　rewrite は仮定にある等式を使ってゴールを書き換えます。下記の例では、リスト xs について帰納法を用いて証明していますが、ゴールの中に含まれる&lt;code&gt;length (xs ++ ys)&lt;/code&gt;を、帰納法の仮定&lt;code&gt;IHxs&lt;/code&gt;を用いてrewriteすることで&lt;code&gt;length xs + length ys&lt;/code&gt;に書き換えています。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_rewrite : forall (A:Set)(xs ys:list A), &lt;br /&gt;Coq &lt; length (xs ++ ys) = length xs + length ys.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall (A : Set) (xs ys : list A),&lt;br /&gt;   length (xs ++ ys) = length xs + length ys&lt;br /&gt;&lt;br /&gt;Sample_of_rewrite &lt; intros A xs ys.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Set&lt;br /&gt;  xs : list A&lt;br /&gt;  ys : list A&lt;br /&gt;  ============================&lt;br /&gt;   length (xs ++ ys) = length xs + length ys&lt;br /&gt;&lt;br /&gt;Sample_of_rewrite &lt; induction xs.                        &lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  A : Set&lt;br /&gt;  ys : list A&lt;br /&gt;  ============================&lt;br /&gt;   length (nil ++ ys) = length nil + length ys&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; length ((a :: xs) ++ ys) = length (a :: xs) + length ys&lt;br /&gt;&lt;br /&gt;Sample_of_rewrite &lt; reflexivity.       &lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Set&lt;br /&gt;  a : A&lt;br /&gt;  xs : list A&lt;br /&gt;  ys : list A&lt;br /&gt;  IHxs : length (xs ++ ys) = length xs + length ys&lt;br /&gt;  ============================&lt;br /&gt;   length ((a :: xs) ++ ys) = length (a :: xs) + length ys&lt;br /&gt;&lt;br /&gt;Sample_of_rewrite &lt; simpl.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Set&lt;br /&gt;  a : A&lt;br /&gt;  xs : list A&lt;br /&gt;  ys : list A&lt;br /&gt;  IHxs : length (xs ++ ys) = length xs + length ys&lt;br /&gt;  ============================&lt;br /&gt;   S (length (xs ++ ys)) = S (length xs + length ys)&lt;br /&gt;&lt;br /&gt;Sample_of_rewrite &lt; rewrite IHxs.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  A : Set&lt;br /&gt;  a : A&lt;br /&gt;  xs : list A&lt;br /&gt;  ys : list A&lt;br /&gt;  IHxs : length (xs ++ ys) = length xs + length ys&lt;br /&gt;  ============================&lt;br /&gt;   S (length xs + length ys) = S (length xs + length ys)&lt;br /&gt;&lt;br /&gt;Sample_of_rewrite &lt; reflexivity.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_rewrite &lt; Qed.&lt;br /&gt;intros A xs ys.&lt;br /&gt;induction xs.&lt;br /&gt; reflexivity.&lt;br /&gt; &lt;br /&gt; simpl in |- *.&lt;br /&gt; rewrite IHxs in |- *.&lt;br /&gt; reflexivity.&lt;br /&gt; &lt;br /&gt;Sample_of_rewrite is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7423820751170054446?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7423820751170054446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7423820751170054446' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7423820751170054446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7423820751170054446'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-rewrite-3-of-25.html' title='[Coq] Coq Advent Calender : rewrite (3 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5356851846990333765</id><published>2010-12-04T05:57:00.002+09:00</published><updated>2010-12-04T06:36:53.076+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : auto (2 of 25)</title><content type='html'>　Coq でよく使われる tactic の２つ目は auto です。&lt;br /&gt;&lt;br /&gt;　Coq は簡単な証明は自動的に証明してくれる機能が幾つかありますが、auto はよく使われます。autoが何をやっているか知りたい場合は、autoの代わりにinfo autoと入力すると、autoの中で何をしてるかが判ります。Coqの初学者にはinfoは便利ですよ。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_auto : forall A B:Prop, ((((A-&gt;B)-&gt;A)-&gt;A)-&gt;B)-&gt;B.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall A B : Prop, ((((A -&gt; B) -&gt; A) -&gt; A) -&gt; B) -&gt; B&lt;br /&gt;&lt;br /&gt;Sample_of_auto &lt; auto.&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_auto &lt; Qed.&lt;br /&gt;auto.&lt;br /&gt;&lt;br /&gt;Sample_of_auto is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5356851846990333765?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5356851846990333765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5356851846990333765' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5356851846990333765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5356851846990333765'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-auto-2-of-25.html' title='[Coq] Coq Advent Calender : auto (2 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8246436948290504769</id><published>2010-12-04T05:26:00.004+09:00</published><updated>2010-12-04T05:42:45.529+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Advent Calender : apply (1 of 25)</title><content type='html'>　&lt;a href="http://d.hatena.ne.jp/tokuhirom/20081216/1229387324"&gt;技術的 Advent Calender &lt;/a&gt;という概念を知らなかったのですが、面白そうなので遅ればせながら始めてみました。という訳で12/1から開始出来なかったのはご容赦下さい。&lt;br /&gt;　先日のCoq Party絡みで集計された&lt;a href="https://gist.github.com/717611"&gt;Coqでよく使われるtacticのリスト&lt;/a&gt;の順に、そのtacticが使われている証明例を書いてみます。&lt;br /&gt;&lt;br /&gt;　最初は apply です。&lt;br /&gt;　「この仮定（下記の例では pq）を使うとゴール（下記の例では Q）が出て来る」という時に、apply pq とすると、ゴール Q が変化します。学校で習う普通の証明の順序と違って、Coqの証明はゴールを一歩一歩、仮定に戻して行きます。その時使うのが apply です。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Coq &lt; Lemma Sample_of_apply : forall P Q:Prop, P -&gt; (P-&gt;Q) -&gt; Q.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall P Q : Prop, P -&gt; (P -&gt; Q) -&gt; Q&lt;br /&gt;&lt;br /&gt;Sample_of_apply &lt; intros P Q p pq.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  p : P&lt;br /&gt;  pq : P -&gt; Q&lt;br /&gt;  ============================&lt;br /&gt;   Q&lt;br /&gt;&lt;br /&gt;Sample_of_apply &lt; apply pq.&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : Prop&lt;br /&gt;  Q : Prop&lt;br /&gt;  p : P&lt;br /&gt;  pq : P -&gt; Q&lt;br /&gt;  ============================&lt;br /&gt;   P&lt;br /&gt;&lt;br /&gt;Sample_of_apply &lt; exact p.  &lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;Sample_of_apply &lt; Qed.&lt;br /&gt;intros P Q p pq.&lt;br /&gt;apply pq.&lt;br /&gt;exact p.&lt;br /&gt;&lt;br /&gt;Sample_of_apply is defined&lt;br /&gt;&lt;br /&gt;Coq &lt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8246436948290504769?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8246436948290504769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8246436948290504769' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8246436948290504769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8246436948290504769'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/12/coq-coq-advent-calender-apply-1-of-25.html' title='[Coq] Coq Advent Calender : apply (1 of 25)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-1060387530721751938</id><published>2010-11-01T23:09:00.001+09:00</published><updated>2010-11-01T23:11:30.748+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TAPL'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[TAPL][Coq] Chapter 3: Boolean Expression</title><content type='html'>TAPLのChapter 3のBoolean式の部分に付いてCoqで証明してみました。&lt;br /&gt;コードは http://ideone.com/COzSO に公開しています。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1060387530721751938?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/1060387530721751938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=1060387530721751938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1060387530721751938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1060387530721751938'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/11/taplcoq-chapter-3-boolean-expression.html' title='[TAPL][Coq] Chapter 3: Boolean Expression'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-6077729679336881253</id><published>2010-10-12T07:55:00.003+09:00</published><updated>2010-10-12T08:03:30.027+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TAPL'/><title type='text'>[TAPL] Types and Programming Languages Reading at Tokyo</title><content type='html'>Types and Programming Languages (通称 TAPL) の読書会の第0回が先日あったので報告。&lt;br /&gt;&lt;br /&gt;TAPL読書会ですが、下記の様にGoogle groupが出来ました。開催情報とか流れるので興味のある方は登録をお勧めします。&lt;br /&gt;http://groups.google.co.jp/group/taplreading-tokyo&lt;br /&gt;次回開催は 11/3午後で、会場は同じく豆蔵オフィスです。&lt;br /&gt;&lt;br /&gt;前回は、Chap.1はスキップ、Chap.2から読み始め、Chap.3の途中まででした。&lt;br /&gt;次回はChap.3の続きから初めて、Chap.4(というか実装のChapterはこの先も)はスキップ、Chap.5を読む予定、となっています。&lt;br /&gt;参加者は予習復習前提で、次回の範囲は予め読んで来ることが前提と、硬派な勉強会ということになりました。&lt;br /&gt;Chap.4のような実装の箇所は各自実装したい人が自分で実装してちょっとデモをするということで。&lt;br /&gt;&lt;br /&gt;参加者ですが、前回は総勢４名もCS専攻の大学院生の方が来てくれたのは良かったです。素人の社会人だけで勉強会してると簡単に行き詰るので。&lt;br /&gt;&lt;br /&gt;懇親会も大変盛り上がっていたようで、大変有意義な一日でした。しかし、積読率高いですね＞TAPL。買ったけど読んでなかったとか、Chap.3までは読んだけどとか、そういう話ばっかり。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-6077729679336881253?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/6077729679336881253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=6077729679336881253' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6077729679336881253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6077729679336881253'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/10/tapl-types-and-programming-languages.html' title='[TAPL] Types and Programming Languages Reading at Tokyo'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-6598058760531735789</id><published>2010-09-26T19:37:00.001+09:00</published><updated>2010-09-26T19:39:39.976+09:00</updated><title type='text'>[event] Reading TAPL</title><content type='html'>Types and Programming Languages ( http://www.amazon.co.jp/dp/0262162091 ) という定番の教科書を読もうという読書会です。&lt;br /&gt;東京近辺の方はぜひどうぞ。&lt;br /&gt;&lt;br /&gt;http://atnd.org/events/8291&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-6598058760531735789?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/6598058760531735789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=6598058760531735789' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6598058760531735789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6598058760531735789'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/09/event-reading-tapl.html' title='[event] Reading TAPL'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-6816845445482218369</id><published>2010-09-20T10:26:00.002+09:00</published><updated>2010-09-20T10:38:13.343+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Fibonacci series including 7110</title><content type='html'>　今更ながら http://recruit.drecom.co.jp/event2010  の「7110を含むフィボナッチ数列で、初期値の組み合わせが一番小さいものをあげろ。※自然数に限る」をScalaで解いてみた。&lt;br /&gt;　もうイベントは終わったから解答公開してもいいよね。&lt;br /&gt;&lt;br /&gt;　fib が 7110以下の範囲のフォボナッチ数列を計算する関数。zipとか使って格好良く書けるかもとも思うが、判りやすさ優先で。ysのところにxs'と書けないScalaは残念な感じだ。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scala&gt; def fib(n0:Int,n1:Int) = {                   &lt;br /&gt;     |   def f(xs:List[Int]):List[Int] = xs match { &lt;br /&gt;     |     case a::b::ys if a &lt; 7110 =&gt; f((a+b)::xs)&lt;br /&gt;     |     case _ =&gt; xs                             &lt;br /&gt;     |   }                                          &lt;br /&gt;     |   f(n1::n0::Nil)                                    &lt;br /&gt;     | }&lt;br /&gt;fib: (Int,Int)List[Int]&lt;br /&gt;&lt;br /&gt;scala&gt; def solve = for( n1 &lt;- (1 to 100).toList;                       &lt;br /&gt;     |   n0 &lt;- (1 to n1).toList if fib(n0,n1).head==7110               &lt;br /&gt;     | ) yield {(n0,n1)}&lt;br /&gt;solve: List[(Int, Int)]&lt;br /&gt;&lt;br /&gt;scala&gt; solve&lt;br /&gt;res7: List[(Int, Int)] = List((16,70), (70,86))&lt;br /&gt;scala&gt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-6816845445482218369?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/6816845445482218369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=6816845445482218369' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6816845445482218369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/6816845445482218369'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/09/scala-fibonacci-series-including-7110.html' title='[Scala] Fibonacci series including 7110'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5001449914103897715</id><published>2010-07-24T23:34:00.004+09:00</published><updated>2010-07-25T00:38:42.374+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq-99 : Part 1</title><content type='html'>　前に&lt;a href="http://aperiodic.net/phil/scala/s-99/"&gt;S-99: Ninety-Nine Scala Problems&lt;/a&gt;というのを紹介しましたが、Coqでも入門者が勉強用に解く為の問題集というのを考えてみました。&lt;br /&gt;&lt;br /&gt;　まずは命題論理の証明の課題。勿論、tautoとかで一発だと思いますが、練習問題なので入門者は自力で解こう。&lt;br /&gt;　&lt;code&gt;Admitted.&lt;/code&gt;を消して証明を書く事が期待されています。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Section Prop_Logic.&lt;br /&gt;  Lemma Coq_01 : forall A B C:Prop, (A-&gt;B-&gt;C) -&gt; (A-&gt;B) -&gt; A -&gt; C.&lt;br /&gt;  Admitted.&lt;br /&gt;  Lemma Coq_02 : forall A B C:Prop, A /\ (B /\ C) -&gt; (A /\ B) /\ C.&lt;br /&gt;  Admitted.&lt;br /&gt;  Lemma Coq_03 : forall A B C D:Prop, (A -&gt; C) /\ (B -&gt; D) /\ A /\ B -&gt; C /\ D.&lt;br /&gt;  Admitted.&lt;br /&gt;  Lemma Coq_04 : forall A : Prop, ~(A /\ ~A).&lt;br /&gt;  Admitted.&lt;br /&gt;  Lemma Coq_05 : forall A B C:Prop, A \/ (B \/ C) -&gt; (A \/ B) \/ C.&lt;br /&gt;  Admitted.&lt;br /&gt;  Lemma Coq_06 : forall A, ~~~A -&gt; ~A.&lt;br /&gt;  Admitted.&lt;br /&gt;  Lemma Coq_07 : forall A B:Prop, (A-&gt;B)-&gt;~B-&gt;~A.&lt;br /&gt;  Admitted.&lt;br /&gt;  Lemma Coq_08: forall A B:Prop, ((((A-&gt;B)-&gt;A)-&gt;A)-&gt;B)-&gt;B.&lt;br /&gt;  Admitted.&lt;br /&gt;  Lemma Coq_09 : forall A:Prop, ~~(A\/~A).&lt;br /&gt;  Admitted.&lt;br /&gt;End Prop_Logic.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;解答例は例えば&lt;a href="http://ideone.com/NzTUJ"&gt;これ&lt;/a&gt;とか。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5001449914103897715?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5001449914103897715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5001449914103897715' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5001449914103897715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5001449914103897715'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/07/coq-coq-99-part-1.html' title='[Coq] Coq-99 : Part 1'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-362693369392465177</id><published>2010-07-24T07:15:00.004+09:00</published><updated>2010-07-24T16:27:47.475+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Joke'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Joke]Falso : HyperVerifier and HyperProver</title><content type='html'>　&lt;a href="https://twitter.com/garriguejej/status/19335981815"&gt;twitter&lt;/a&gt;で知ったジョークサイトなんだが、&lt;a href="http://estatis.coders.fm/falso/"&gt;Falso, by Estatis Inc.&lt;/a&gt;があります。&lt;br /&gt;&lt;br /&gt;　「ある公理を導入すれば」なんでも証明出来てしまう(笑)という話で、それをいかにも画期的新製品みたいな感じに仕上げているのがおかしい。&lt;br /&gt;&lt;br /&gt;　追記：&lt;a href="http://togetter.com/li/37411"&gt;togetter: Falso 定理証明系の大革命&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-362693369392465177?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/362693369392465177/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=362693369392465177' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/362693369392465177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/362693369392465177'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/07/jokefalso-hyperverifier-and-hyperprover.html' title='[Joke]Falso : HyperVerifier and HyperProver'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-467871906988373504</id><published>2010-07-19T23:33:00.003+09:00</published><updated>2010-07-19T23:42:42.833+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maude'/><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><title type='text'>[FM] Maude</title><content type='html'>　今日は&lt;a href="http://groups.google.co.jp/group/fm-forum"&gt;Formal Methods Forum&lt;/a&gt;の勉強会で、いつものCoq (CPDT)の話の他に、&lt;a href="http://maude.cs.uiuc.edu/"&gt;Maude&lt;/a&gt;をちょっと触ってみた、という話をしました。&lt;br /&gt;&lt;br /&gt;　Maudeは項書き換え系の言語で形式仕様記述やモデル検査、DSL記述などにも使える言語です。&lt;br /&gt;　Coqと違って証明も出来るけどメインは仕様記述＆それ自体がプロトタイプとして動く、かなぁ。パズルとかにも役に立つかも。&lt;br /&gt;&lt;br /&gt;　あわてて作った資料なんで完成度は低いですがこちら。&lt;br /&gt;&lt;a href="http://www.slideshare.net/tmiya/maude20100719"&gt;Slideshare上のプレゼン&lt;/a&gt;&lt;br /&gt;&lt;a href="http://homepage.mac.com/takashi_miyamoto/coq/maude20100719.pdf"&gt;PDF資料&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;　Maudeに興味のある方はコメント頂けると嬉しいです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-467871906988373504?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/467871906988373504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=467871906988373504' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/467871906988373504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/467871906988373504'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/07/fm-maude.html' title='[FM] Maude'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5405599067950603165</id><published>2010-07-03T14:20:00.002+09:00</published><updated>2010-07-03T14:24:54.630+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] CoqUn -- Summer Coq Event in Nagoya</title><content type='html'>　2010/08/29に名古屋で&lt;a href="http://atnd.org/events/6022"&gt;Coq庵 -- 日本の夏、証明の夏&lt;/a&gt;というCoqのイベントが開催されます。&lt;br /&gt;　といっても、Coqユーザが集まって話をしようという比較的緩いイベントなんで、Coq初めてという人も参加すると良いのではなかろうか。入門的な話もあります。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5405599067950603165?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5405599067950603165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5405599067950603165' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5405599067950603165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5405599067950603165'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/07/coq-coqun-summer-coq-event-in-nagoya.html' title='[Coq] CoqUn -- Summer Coq Event in Nagoya'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8015740989439950869</id><published>2010-07-03T13:47:00.003+09:00</published><updated>2010-07-03T14:10:18.541+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Puzzle from Hiyama-san's Blog</title><content type='html'>　檜山さんのblogに&lt;a href="http://d.hatena.ne.jp/m-hiyama/20100629/1277774676"&gt;掛け算から足し算を作る（パズルとしてやってみよう）&lt;/a&gt;という問題が載っています。&lt;br /&gt;　Coqの練習問題としてちょうど良いかと思い解いてみました。&lt;br /&gt;　思ったより時間がかかってしまい、解き終わる前にネタばらしが出ちゃったのだけど、一応、解いた解答です。&lt;a href="http://ideone.com/Staa3"&gt;http://ideone.com/Staa3&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;　分配則は簡単だったが、交換則を思いつくまでに苦労した。交換測を思いついたらその延長で結合則もなんとか。ただ、証明はちまちまとrewriteしてるだけ。ここは本当は自動化できるんだろうなぁ。&lt;br /&gt;　Coq初心者的には、inv関係の&lt;code&gt;{a'|a*a'=1}&lt;/code&gt;みたいな記法の使い方に慣れたのが良かったか。あと&lt;code&gt;Axiom eq_dec_0:forall a:G, {a=0}+{a&lt;&gt;0}&lt;/code&gt;みたいなdecide出来る公理の便利さを実感した。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8015740989439950869?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8015740989439950869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8015740989439950869' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8015740989439950869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8015740989439950869'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/07/coq-puzzle-from-hiyama-sans-blog.html' title='[Coq] Puzzle from Hiyama-san&apos;s Blog'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5092419841713692542</id><published>2010-06-14T22:39:00.003+09:00</published><updated>2010-06-14T23:39:36.441+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Scala 2.8 Continuation (1)</title><content type='html'>&lt;a href="http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/continuations/trunk/doc/examples/continuations"&gt;root/compiler-plugins/continuations/trunk/doc/examples/continuations&lt;/a&gt;に載っているサンプルコードをREPLで写経してみます。&lt;br /&gt;&lt;br /&gt;Test0.scala&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scala&gt; import scala.util.continuations._            &lt;br /&gt;import scala.util.continuations._&lt;br /&gt;&lt;br /&gt;scala&gt; reset {                                      &lt;br /&gt;     |   2 * {                                      &lt;br /&gt;     |     println("up")                            &lt;br /&gt;     |     val x = shift((k:Int=&gt;Int) =&gt; k(k(k(8))))&lt;br /&gt;     |     println("down")                          &lt;br /&gt;     |     x                                        &lt;br /&gt;     |   }                                          &lt;br /&gt;     | }&lt;br /&gt;up&lt;br /&gt;down&lt;br /&gt;down&lt;br /&gt;down&lt;br /&gt;res1: Int = 64&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;これは&lt;code&gt;def k(i:Int):Int = {println("down"); 2*i}&lt;/code&gt;と考えればOK。&lt;br /&gt;&lt;br /&gt;Test1.scala&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scala&gt; object Test1 {                                 &lt;br /&gt;     |   def testThisMethod() = {                     &lt;br /&gt;     |     1 + (shift((k:Int=&gt;Int) =&gt; k(k(k(17)))))   &lt;br /&gt;     |   }&lt;br /&gt;     |   def testThisCallingMethod() = {              &lt;br /&gt;     |     testThisMethod() * 2                       &lt;br /&gt;     |   }&lt;br /&gt;     |   def m() {&lt;br /&gt;     |     val result = reset(testThisCallingMethod())&lt;br /&gt;     |     println(result)&lt;br /&gt;     |   }&lt;br /&gt;     | }&lt;br /&gt;defined module Test1&lt;br /&gt;&lt;br /&gt;// ((((((17 + 1) * 2) + 1) * 2) + 1) * 2) = 150&lt;br /&gt;&lt;br /&gt;scala&gt; Test1.m()                                      &lt;br /&gt;150&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;k = (_+1)*2 と考えればこれも予想通りの結果。&lt;br /&gt;resetの中にshiftを書くのはOKだが、resetなしでshiftだけの関数を定義しようとすると下記の様にエラーになります。仕方が無いので&lt;code&gt;object Test1 {...}&lt;/code&gt; に包みます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scala&gt; def testThisMethod() = {&lt;br /&gt;     |   1 + (shift((k:Int=&gt;Int) =&gt; k(k(k(17)))))&lt;br /&gt;     | }&lt;br /&gt;&lt;console&gt;:2: error: type mismatch;&lt;br /&gt; found   : Int @scala.util.continuations.cpsSynth @scala.util.continuations.cpsParam[Int,Int]&lt;br /&gt; required: Int&lt;br /&gt;object RequestResult$line4$object {&lt;br /&gt;                                  ^&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Test2.scala&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scala&gt; object Test2 {                             &lt;br /&gt;     |   def methA() = {                          &lt;br /&gt;     |     def fun(k:Int=&gt;String) = {             &lt;br /&gt;     |       for(i &lt;- List(1,2,3,4)) println(k(i))&lt;br /&gt;     |       Some("returnvalue")                  &lt;br /&gt;     |     }                                      &lt;br /&gt;     |     2 * shift(fun)                         &lt;br /&gt;     |   }&lt;br /&gt;     |   def methB() = {                          &lt;br /&gt;     |     "+++ "+methA().toString()              &lt;br /&gt;     |   }&lt;br /&gt;     |   def m() = reset(methB())                 &lt;br /&gt;     | }&lt;br /&gt;defined module Test2&lt;br /&gt;&lt;br /&gt;scala&gt; Test2.m()&lt;br /&gt;+++ 2&lt;br /&gt;+++ 4&lt;br /&gt;+++ 6&lt;br /&gt;+++ 8&lt;br /&gt;res0: Some[java.lang.String] = Some(returnvalue)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;code&gt;k = "+++" + (2 * _).toString() &lt;/code&gt;ですか。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5092419841713692542?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5092419841713692542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5092419841713692542' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5092419841713692542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5092419841713692542'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/06/scala-scala-28-continuation-1.html' title='[Scala] Scala 2.8 Continuation (1)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-1528266795489184800</id><published>2010-06-13T23:03:00.005+09:00</published><updated>2010-06-13T23:30:48.733+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Scala 2.8 RC4 and continuation plugin</title><content type='html'>　Scala 2.8 RC4 が出ました --- が、なんかバグがあるらしく来週には RC5 が出るそうです。なんか品質安定しませんね＞Scala 2.8。&lt;br /&gt;&lt;br /&gt;　RC4からは限定継続のコンパイラプラグインが付属される様になりました。&lt;br /&gt;　使い方はこんな感じ。Scala 2.8 RC4を導入したディレクトリに居るとします。pluginにパスを通し、continuationをenableにする必要があります。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;% cd ~/scala28rc4&lt;br /&gt;% ./bin/scala -Xpluginsdir ./misc/scala-devel/plugins/ ¥&lt;br /&gt;-Xplugin:continuations -P:continuations:enable&lt;br /&gt;Welcome to Scala version 2.8.0.RC4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).&lt;br /&gt;Type in expressions to have them evaluated.&lt;br /&gt;Type :help for more information.&lt;br /&gt;&lt;br /&gt;scala&gt; import scala.util.continuations._         &lt;br /&gt;import scala.util.continuations._&lt;br /&gt;&lt;br /&gt;scala&gt; reset {&lt;br /&gt;     |   shift { (k:Int=&gt;Int) =&gt;&lt;br /&gt;     |     k(k(k(7)))&lt;br /&gt;     |   } + 1&lt;br /&gt;     | }&lt;br /&gt;res0: Int = 10&lt;br /&gt;&lt;br /&gt;scala&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;限定継続をおいおい勉強しようと思います。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1528266795489184800?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/1528266795489184800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=1528266795489184800' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1528266795489184800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1528266795489184800'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/06/scala-scala-28-rc4-and-continuation.html' title='[Scala] Scala 2.8 RC4 and continuation plugin'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7030277025930087925</id><published>2010-05-20T22:25:00.002+09:00</published><updated>2010-05-21T00:40:15.567+09:00</updated><title type='text'>[Coq] How to define complex inductions</title><content type='html'>Coq の証明の書き方パターンを yoshihiro503 さんに教わったので、忘れないうちに。&lt;br /&gt;&lt;br /&gt;自然数に関する定理を証明したい場合に、下記の様な補題が欲しかったとします。&lt;br /&gt;&lt;pre&gt;Lemma nat2_ind : forall P:nat -&gt; Prop, P 0 -&gt; P 1 -&gt;&lt;br /&gt;  (forall n:nat, P n -&gt; P (S n) -&gt; P (S (S n))) -&gt;&lt;br /&gt;  (forall n:nat, P n).&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://ideone.com/YN0ks"&gt;教わったコード&lt;/a&gt;を元に自分なりに書いてみたのが下記の証明です。&lt;br /&gt;&lt;pre&gt;  &lt;br /&gt;  ============================&lt;br /&gt;   forall P : nat -&gt; Prop,&lt;br /&gt;   P 0 -&gt;&lt;br /&gt;   P 1 -&gt;&lt;br /&gt;   (forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))) -&gt; forall n : nat, P n&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; intros P H0 H1 IH.          &lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : nat -&gt; Prop&lt;br /&gt;  H0 : P 0&lt;br /&gt;  H1 : P 1&lt;br /&gt;  IH : forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))&lt;br /&gt;  ============================&lt;br /&gt;   forall n : nat, P n&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; refine (fix ll n : P n := _).     (* ここで refine を使って ll を定義するのがポイント *)&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : nat -&gt; Prop&lt;br /&gt;  H0 : P 0&lt;br /&gt;  H1 : P 1&lt;br /&gt;  IH : forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))&lt;br /&gt;  ll : forall n : nat, P n&lt;br /&gt;  n : nat&lt;br /&gt;  ============================&lt;br /&gt;   P n&lt;br /&gt;&lt;br /&gt;(* しかしここで apply ll しても駄目。llはIHの仮定のところで使う *)&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; induction n.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  P : nat -&gt; Prop&lt;br /&gt;  H0 : P 0&lt;br /&gt;  H1 : P 1&lt;br /&gt;  IH : forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))&lt;br /&gt;  ll : forall n : nat, P n&lt;br /&gt;  ============================&lt;br /&gt;   P 0&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; P (S n)&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; exact H0.  (* n=0 のケースは P 0 *)&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : nat -&gt; Prop&lt;br /&gt;  H0 : P 0&lt;br /&gt;  H1 : P 1&lt;br /&gt;  IH : forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))&lt;br /&gt;  ll : forall n : nat, P n&lt;br /&gt;  n : nat&lt;br /&gt;  IHn : P n&lt;br /&gt;  ============================&lt;br /&gt;   P (S n)&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; induction n.&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  P : nat -&gt; Prop&lt;br /&gt;  H0 : P 0&lt;br /&gt;  H1 : P 1&lt;br /&gt;  IH : forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))&lt;br /&gt;  ll : forall n : nat, P n&lt;br /&gt;  IHn : P 0&lt;br /&gt;  ============================&lt;br /&gt;   P 1&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; P (S (S n))&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; exact H1.  (* n=1 のケース *)&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : nat -&gt; Prop&lt;br /&gt;  H0 : P 0&lt;br /&gt;  H1 : P 1&lt;br /&gt;  IH : forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))&lt;br /&gt;  ll : forall n : nat, P n&lt;br /&gt;  n : nat&lt;br /&gt;  IHn : P (S n)&lt;br /&gt;  IHn0 : P n -&gt; P (S n)&lt;br /&gt;  ============================&lt;br /&gt;   P (S (S n))&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; apply IH.   (* IH を使う *)&lt;br /&gt;2 subgoals&lt;br /&gt;  &lt;br /&gt;  P : nat -&gt; Prop&lt;br /&gt;  H0 : P 0&lt;br /&gt;  H1 : P 1&lt;br /&gt;  IH : forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))&lt;br /&gt;  ll : forall n : nat, P n&lt;br /&gt;  n : nat&lt;br /&gt;  IHn : P (S n)&lt;br /&gt;  IHn0 : P n -&gt; P (S n)&lt;br /&gt;  ============================&lt;br /&gt;   P n&lt;br /&gt;&lt;br /&gt;subgoal 2 is:&lt;br /&gt; P (S n)&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; apply ll.  (* IHの仮定のところにはll を使ってOK *)&lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : nat -&gt; Prop&lt;br /&gt;  H0 : P 0&lt;br /&gt;  H1 : P 1&lt;br /&gt;  IH : forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))&lt;br /&gt;  ll : forall n : nat, P n&lt;br /&gt;  n : nat&lt;br /&gt;  IHn : P (S n)&lt;br /&gt;  IHn0 : P n -&gt; P (S n)&lt;br /&gt;  ============================&lt;br /&gt;   P (S n)&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; apply IHn0.          &lt;br /&gt;1 subgoal&lt;br /&gt;  &lt;br /&gt;  P : nat -&gt; Prop&lt;br /&gt;  H0 : P 0&lt;br /&gt;  H1 : P 1&lt;br /&gt;  IH : forall n : nat, P n -&gt; P (S n) -&gt; P (S (S n))&lt;br /&gt;  ll : forall n : nat, P n&lt;br /&gt;  n : nat&lt;br /&gt;  IHn : P (S n)&lt;br /&gt;  IHn0 : P n -&gt; P (S n)&lt;br /&gt;  ============================&lt;br /&gt;   P n&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; apply ll.  (* もう一度 ll を使う *)&lt;br /&gt;Proof completed.&lt;br /&gt;&lt;br /&gt;nat2_ind &lt; Qed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;そもそもの証明のゴールをrefineを使って&lt;code&gt;ll&lt;/code&gt;として定義して、証明の中で&lt;code&gt;ll&lt;/code&gt;を使っているので非常に不思議なのですが、変な所（例えばrefine直後に）で&lt;code&gt;apply ll&lt;/code&gt;してProof CompleteしてもQedしたとたんにエラーになります。エラーが出ない様に&lt;code&gt;H0,H1,IH&lt;/code&gt;を使えば、証明が正しい事になります。&lt;br /&gt;&lt;br /&gt;なお、同じ定理を短く書くと&lt;a href="http://ideone.com/vIyGq"&gt;kikxさんの証明ゴルフ&lt;/a&gt;みたいになるようです。すごい。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7030277025930087925?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7030277025930087925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7030277025930087925' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7030277025930087925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7030277025930087925'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/05/coq-how-to-define-complex-inductions.html' title='[Coq] How to define complex inductions'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-1863405462318528705</id><published>2010-05-15T17:41:00.004+09:00</published><updated>2010-05-17T12:52:32.996+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Arithmetic in Coq : N</title><content type='html'>&lt;code&gt;N&lt;/code&gt;は二進数で表現された自然数の型です。&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Require Import NArith.&lt;/code&gt;すると使用出来ます。型の定義は下記の様です。&lt;br /&gt;&lt;pre&gt;Inductive N : Set :=  N0 : N | Npos : positive -&gt; N&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;positive&lt;/code&gt;は下記の様に定義されています。&lt;br /&gt;&lt;pre&gt;Inductive positive : Set :=&lt;br /&gt;    xI : positive -&gt; positive | xO : positive -&gt; positive | xH : positive&lt;/pre&gt;&lt;br /&gt;こんな感じで正の数を表現しています。xHが最上位ビットで、xIが x -&gt; 2x+1, xOが x -&gt; 2x ということです。&lt;br /&gt;&lt;pre&gt;Coq &lt; Check (xO (xI (xO xH))).&lt;br /&gt;10%positive : positive&lt;/pre&gt;&lt;br /&gt;これは&lt;code&gt;(1~0~1~0)%positive.&lt;/code&gt;とも書けます。&lt;br /&gt;&lt;br /&gt;&lt;code&gt;nat&lt;/code&gt;との変換は下記で可能。&lt;br /&gt;&lt;pre&gt;nat_of_N : N -&gt; nat&lt;br /&gt;N_of_nat : nat -&gt; N&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;演算子は&lt;br /&gt;&lt;pre&gt;Ndouble_plus_one, Ndouble : N -&gt; N&lt;br /&gt;Nsucc, Npred : N -&gt; N&lt;br /&gt;Nplus, Nminus, Nmult : N -&gt; N -&gt; N　。+, -, * もあり。&lt;br /&gt;Ncompare : N -&gt; N -&gt; comparison 。Infixで ?=&lt;br /&gt;  comparisonは、&lt;br /&gt;  Inductive comparison : Set :=&lt;br /&gt;    Eq : comparison | Lt : comparison | Gt : comparison&lt;br /&gt;Nlt, Ngt, Nle, Nge : N -&gt; N -&gt; Prop　。Infix で &lt;, &lt;=, &gt;, &gt;=&lt;br /&gt;Nmin, Nmax : N -&gt; N -&gt; N&lt;br /&gt;Ndiv2 : N -&gt; N&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Nに関する帰納法は次の２つの好きな方を使える。Nrectを用いてNindもある。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;N_ind_double&lt;br /&gt;     : forall (a : N) (P : N -&gt; Prop),&lt;br /&gt;       P 0%N -&gt;&lt;br /&gt;       (forall a0 : N, P a0 -&gt; P (Ndouble a0)) -&gt;&lt;br /&gt;       (forall a0 : N, P a0 -&gt; P (Ndouble_plus_one a0)) -&gt; P a&lt;br /&gt;Nrect&lt;br /&gt;     : forall P : N -&gt; Type,&lt;br /&gt;       P 0%N -&gt; (forall n : N, P n -&gt; P (Nsucc n)) -&gt; forall n : N, P n&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Require Import ZArith.ZOdiv.&lt;/code&gt;すれば、&lt;br /&gt;&lt;pre&gt;Ndiv_eucl : N -&gt; N -&gt; N * N&lt;br /&gt;Ndiv : N -&gt; N -&gt; N&lt;br /&gt;Nmod : N -&gt; N -&gt; N&lt;br /&gt;Theorem Ndiv_eucl_correct: forall a b,&lt;br /&gt;  let (q,r) := Ndiv_eucl a b in a = (q * b + r)%N.&lt;/pre&gt;&lt;br /&gt;と除算も使える。&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;追記&lt;br /&gt;ZArith.ZOdivと、ZArithの中でImportしてるZArith.Zdivとは互換性無いのだな。&lt;br /&gt;ZArithを使わないことはまず無いので、ZOdivは使わないほうがよさそう。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1863405462318528705?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/1863405462318528705/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=1863405462318528705' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1863405462318528705'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1863405462318528705'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/05/coq-arithmetic-in-coq-n.html' title='[Coq] Arithmetic in Coq : N'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2903849368903222562</id><published>2010-05-14T23:19:00.004+09:00</published><updated>2010-05-15T00:12:35.267+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Arithmetic in Coq : nat</title><content type='html'>Coqで大きな自然数あるいは整数を使いたくなったので調べてみました。&lt;br /&gt;&lt;br /&gt;★nat&lt;br /&gt;&lt;br /&gt;　Coqで自然数というと基本は&lt;code&gt;nat&lt;/code&gt;です。natというと自分で作る物であるかの様な気すらしますが勿論標準で備わっています。&lt;br /&gt;　&lt;code&gt;nat&lt;/code&gt;を使う場合&lt;code&gt;Require Import Arith.&lt;/code&gt;すると標準ライブラリが使えます。&lt;br /&gt;&lt;br /&gt;●基本&lt;br /&gt;&lt;code&gt;Init.Peano&lt;/code&gt;の中で、&lt;code&gt;pred, plus, mult, le, lt, ge, gt&lt;/code&gt;が定義されていてImport不要で使える。&lt;br /&gt;&lt;br /&gt;●大小比較関係&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;- eq_nat : nat -&gt; nat -&gt; Prop&lt;br /&gt;-- heorem eq_nat_decide : forall n m, {eq_nat n m} + {~ eq_nat n m}. が使える&lt;br /&gt;- lt_eq_lt_dec n m : {n &lt; m} + {n = m} + {m &lt; n}. こんな感じで使う&lt;br /&gt;Definition nat_compare (n m:nat) :=&lt;br /&gt;  match lt_eq_lt_dec n m with &lt;br /&gt;    | inleft (left _) =&gt; Lt&lt;br /&gt;    | inleft (right _) =&gt; Eq&lt;br /&gt;    | inright _ =&gt; Gt&lt;br /&gt;  end.&lt;br /&gt;-- le_lt_dec n m : {n &lt;= m} + {m &lt; n}. など&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;●四則演算&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;- 末尾再帰なtail_plusというのもある&lt;br /&gt;- minus : nat -&gt; nat -&gt; nat. n - m とかも書ける。結果が負になる場合もOを返す。&lt;br /&gt;- min, max : nat -&gt; nat -&gt; nat.&lt;br /&gt;- div2, double : nat -&gt; nat.&lt;br /&gt;- 除算は無いが、Require Import Arith.Euclid. すれば商と剰余には下記がある&lt;br /&gt;-- quotient : forall n, n &gt; 0 -&gt;&lt;br /&gt;    forall m:nat, {q : nat | exists r : nat, m = q * n + r /\ n &gt; r}.&lt;br /&gt;-- modulo : forall n, n &gt; 0 -&gt;&lt;br /&gt;    forall m:nat, {r : nat | exists q : nat, m = q * n + r /\ n &gt; r}.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2903849368903222562?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2903849368903222562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2903849368903222562' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2903849368903222562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2903849368903222562'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/05/coq-arithmetic-in-coq-nat.html' title='[Coq] Arithmetic in Coq : nat'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7936221068989572636</id><published>2010-05-13T23:08:00.002+09:00</published><updated>2010-05-14T01:21:25.518+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FoCaLize'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] FoCaLize Tutorial (2)</title><content type='html'>　&lt;a href="http://study-func-prog.blogspot.com/2010/05/coq-focalize-tutorial-1.html"&gt;[Coq] FoCaLize Tutorial (2)&lt;/a&gt;の続き。&lt;br /&gt;&lt;br /&gt;　前回の&lt;code&gt;extsubset.fcl&lt;/code&gt;に&lt;pre&gt;  theorem incl_remove_mem : all s : Self, all v : Val,&lt;br /&gt;                            ~(v &lt;&lt; s) -&gt; s &lt;: s - v&lt;br /&gt;    proof = by property mem_congr, mem_remove, mem_incl ;&lt;/pre&gt;を追加すると自動証明が失敗するのでFoCaLizeの手動証明を試す予定なのだが...自動証明がそのまま通るみたいだ。&lt;br /&gt;&lt;br /&gt;　が、ここは一応Tutorial通り、手動証明も試してみる事にする、証明を下記の様に直してみる。&lt;pre&gt;    proof = &lt;1&gt;1 assume s : Self, v : Val, hypothesis Hv : ~(v &lt;&lt; s),&lt;br /&gt;                 prove s &lt;: s - v&lt;br /&gt;              &lt;2&gt;1 assume w : Val, hypothesis Hw : w &lt;&lt; s,&lt;br /&gt;                   prove w &lt;&lt; s - v&lt;br /&gt;                &lt;3&gt;1 prove ~(Val!( = )(w, v)) /\ w &lt;&lt; s&lt;br /&gt;                  &lt;4&gt;1 prove ~(Val!( = )(w, v))&lt;br /&gt;                       by property mem_congr hypothesis Hv, Hw&lt;br /&gt;                  &lt;4&gt;2 prove w &lt;&lt; s&lt;br /&gt;                       by hypothesis Hw&lt;br /&gt;                  &lt;4&gt;f conclude&lt;br /&gt;                &lt;3&gt;f qed by property mem_remove step &lt;3&gt;1&lt;br /&gt;              &lt;2&gt;f qed by property mem_incl step &lt;2&gt;1&lt;br /&gt;            &lt;1&gt;f conclude ;&lt;/pre&gt;&lt;br /&gt;再度コンパイルするとこれでも通る。上記の様に手で証明を記述しても生成されたCoqの証明は短く分割されて読みやすくはなるもののやはり人間向けの証明とは言えない感じである。&lt;br /&gt;&lt;br /&gt;証明に通らない例として&lt;pre&gt;  theorem remove_insert : all s : Self, all v : Val,&lt;br /&gt;                          v &lt;&lt; s -&gt; s = (s - v) + v&lt;br /&gt;    proof = &lt;1&gt;1 assume s : Self, v : Val, hypothesis Hv : v &lt;&lt; s,&lt;br /&gt;                 prove s = (s - v) + v&lt;br /&gt;              &lt;2&gt;1 assume w : Val, hypothesis Hw : w &lt;&lt; s,&lt;br /&gt;                   prove w &lt;&lt; (s - v) + v&lt;br /&gt;                   by property mem_insert, mem_remove&lt;br /&gt;              &lt;2&gt;2 assume w : Val, hypothesis Hw : w &lt;&lt; (s - v) + v,&lt;br /&gt;                   prove w &lt;&lt; s&lt;br /&gt;                   by property mem_insert, mem_remove, mem_congr, Val!diff_eq&lt;br /&gt;              &lt;2&gt;f qed by property eq_incl, mem_incl step &lt;2&gt;1, &lt;2&gt;2&lt;br /&gt;            &lt;1&gt;f conclude ;&lt;/pre&gt;&lt;br /&gt;を試すと下記の様にエラーが出る。&lt;pre&gt;% ~/pkg/bin/focalizec extsubset.fcl&lt;br /&gt;Invoking ocamlc...&lt;br /&gt;&gt;&gt; /Users/miyamoto/pkg/focalize-0.6.0/bin/ocamlc -I /Users/miyamoto/pkg/lib/focalizec-0.6.0 -c extsubset.ml&lt;br /&gt;Invoking zvtov...&lt;br /&gt;&gt;&gt; /Users/miyamoto/pkg/focalize-0.6.0/bin/zvtov -zenon /Users/miyamoto/pkg/focalize-0.6.0/bin/zenon -new extsubset.zv&lt;br /&gt;File "extsubset.fcl", line 61, characters 19-53:                &lt;br /&gt;Zenon error: could not find a proof within the memory size limit&lt;br /&gt;### proof failed&lt;br /&gt;%&lt;/pre&gt;これについてもチュートリアルに従い証明を完全に記述するとコンパイルに通る。&lt;br /&gt;&lt;br /&gt;　なんとなくCoqに慣れてしまったので、FoCaLizeを用いて証明を記述する方が寧ろ判りにくいようにも思う。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7936221068989572636?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7936221068989572636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7936221068989572636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7936221068989572636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7936221068989572636'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/05/coq-focalize-tutorial-2.html' title='[Coq] FoCaLize Tutorial (2)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-250990580170034694</id><published>2010-05-10T20:27:00.004+09:00</published><updated>2010-05-10T22:28:25.623+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FoCaLize'/><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] FoCaLize Tutorial (1)</title><content type='html'>　形式手法開発ツールの&lt;a href="http://focalize.inria.fr/"&gt;FoCaLize&lt;/a&gt;をインストールして動かしてみました。&lt;br /&gt;&lt;br /&gt;　FoCaLizeは言語名かつツール群の総称です。言語としては、ちょっとオブジェクト指向風（継承などの要素があったり、speciesというクラスっぽいものがある）な純粋関数型言語で、FoCaLizeという言語で書いたプログラムは、OCamlのコードが生成されると共に、（ちょっとしたヒントを人間が与える事で）Zenonという自動証明器がCoq用の証明を自動生成します。&lt;br /&gt;　多分、普通のJavaプログラマとかには、素のCoqよりもFoCaLizeの方が習得しやすい思われる。逆にバリバリのOCamlerみたいな人には素のCoqを使う方が楽なんじゃなかろうか。&lt;br /&gt;　開発元は例によってCoqなどと同じINRIAです。Coq界隈だけでもCoq自体に、FoCaLizeに、Ynotにとなんかツールが多過ぎて全然勉強がおいつきません。&lt;br /&gt;&lt;br /&gt;★インストール&lt;br /&gt;&lt;br /&gt;&lt;a href="http://focalize.inria.fr/download/"&gt;Download&lt;/a&gt;からtar ballをダウンロードして、&lt;br /&gt;&lt;pre&gt;# ./configure&lt;br /&gt;# make&lt;br /&gt;# make install&lt;/pre&gt;&lt;br /&gt;するとOK。Coqが既に動くならそんなに大変じゃないと思う。（前提にghostscriptを要求されたり良く解らんところもあるが）&lt;br /&gt;&lt;br /&gt;★superset.fcl&lt;br /&gt;&lt;br /&gt;&lt;a href="http://focalize.inria.fr/documentation/focalize-0.6.0_tutorial.pdf"&gt;Tutorial&lt;/a&gt;に従い、まずはsuperset.fclをコンパイルしてみます。下記を superset.fcl として入力。文法は概ねOCaml風です。&lt;br /&gt;&lt;pre&gt;use "basics" ;;&lt;br /&gt;species Superset =&lt;br /&gt;  signature ( = ) : Self -&gt; Self -&gt; basics#bool ;&lt;br /&gt;  property eq_refl : all x : Self, x = x ;&lt;br /&gt;  property eq_symm : all x y : Self, x = y -&gt; y = x ;&lt;br /&gt;  property eq_tran : all x y z : Self, x = y -&gt; y = z -&gt; x = z ;&lt;br /&gt;  theorem eq_symmtran : all x y z : Self, x = y -&gt; x = z -&gt; y = z&lt;br /&gt;    proof = by property eq_symm, eq_tran ;&lt;br /&gt;end ;;&lt;/pre&gt;内容は大体見当がつくと思います。&lt;code&gt;Self&lt;/code&gt;というのは、OOな用語で言えば自クラスのことで、自インスタンス(Javaのthis)ではありません --- まぁ&lt;br /&gt;&lt;code&gt;Self -&gt; Self -&gt; basics#bool&lt;/code&gt;&lt;br /&gt;を見ればそれは判るか。&lt;br /&gt;&lt;br /&gt;&lt;code&gt;% focalizec superset.fcl&lt;/code&gt;&lt;br /&gt;でコンパイルすると、OCamlのコード (superset.ml) とかTheoremの証明 (superset.v) などが生成されます。eq_symm, eq_tran を使え、と指示するだけで自動証明されるのでCoqとかに不慣れでも使いやすいかも。ただ生成される証明が&lt;br /&gt;&lt;pre&gt;exact(&lt;br /&gt;(NNPP _ (fun zenon_G=&gt;(zenon_notallex (fun x:abst_T=&gt;(forall y:abst_T,(&lt;br /&gt;forall z:abst_T,((Is_true (abst__equal_ x y))-&gt;((Is_true (abst__equal_&lt;br /&gt;x z))-&gt;(Is_true (abst__equal_ y z))))))) (fun zenon_H2a=&gt;(zenon_ex&lt;br /&gt;abst_T (fun x:abst_T=&gt;(~(forall y:abst_T,(forall z:abst_T,((Is_true (&lt;br /&gt;   ...47行省略...&lt;br /&gt;abst_eq_tran)))) zenon_H1b)) (zenon_notnot _ (refl_equal (abst__equal_&lt;br /&gt;zenon_Tz_k zenon_Ty_e))) zenon_Hb)) zenon_H8 zenon_H9)) in (zenon_noteq&lt;br /&gt;_ zenon_Ty_e zenon_H7)))) (fun zenon_H5=&gt;(zenon_H6 zenon_H5)) zenon_H22)&lt;br /&gt;) zenon_H23)) abst_eq_symm)) zenon_H24)) zenon_H25)) zenon_H26))&lt;br /&gt;zenon_H27)) zenon_H28)) zenon_H29)) zenon_H2a)) zenon_G)))).&lt;/pre&gt;&lt;br /&gt;みたいな感じで、人間が読む証明じゃないよなー。あと&lt;code&gt;NNPP : forall p : Prop, ~ ~ p -&gt; p&lt;/code&gt;を使うのありなんだ、みたいな。&lt;br /&gt;&lt;br /&gt;★subset.fcl&lt;br /&gt;&lt;br /&gt;同様にsubset.fclを入力。&lt;br /&gt;&lt;pre&gt;use "basics" ;;&lt;br /&gt;open "superset" ;;&lt;br /&gt;&lt;br /&gt;species Subset(Val is Superset) =&lt;br /&gt;  signature ( &lt;&lt; ) : Val -&gt; Self -&gt; basics#bool ;&lt;br /&gt;&lt;br /&gt;  signature empty : Self ;&lt;br /&gt;  property mem_empty : all v : Val, ~(v &lt;&lt; empty) ;&lt;br /&gt;&lt;br /&gt;  signature ( + ) : Self -&gt; Val -&gt; Self ;&lt;br /&gt;  property mem_insert : all v1 v2 : Val, all s : Self,&lt;br /&gt;                        v1 &lt;&lt; s + v2 &lt;-&gt;&lt;br /&gt;                        (Val!( = )(v1, v2) \/ v1 &lt;&lt; s) ;&lt;br /&gt;&lt;br /&gt;  signature ( - ) : Self -&gt; Val -&gt; Self ;&lt;br /&gt;  property mem_remove : all v1 v2 : Val, all s : Self,&lt;br /&gt;                        v1 &lt;&lt; s - v2 &lt;-&gt;&lt;br /&gt;                        (~(Val!( = )(v1, v2)) /\ v1 &lt;&lt; s) ;&lt;br /&gt;end ;;&lt;/pre&gt;&lt;br /&gt;　内容は見れば判ると思いますが&lt;code&gt;&lt;&lt;, +, -&lt;/code&gt;が集合の∈、要素の追加、削除に対応します。&lt;code&gt;Val!( = )&lt;/code&gt;とうのは&lt;code&gt;Val&lt;/code&gt;クラスの&lt;code&gt;( = )&lt;/code&gt;メソッドを呼び出す、みたいな意味です。&lt;br /&gt;&lt;br /&gt;★extsubset.fcl&lt;br /&gt;&lt;br /&gt;次に継承を使う例を。ExtSubsetはSubsetを継承します。&lt;br /&gt;&lt;pre&gt;use "basics" ;;&lt;br /&gt;open "superset" ;;&lt;br /&gt;open "subset" ;;&lt;br /&gt;&lt;br /&gt;species ExtSubset(Val is Superset) =&lt;br /&gt;  inherit Superset, Subset(Val) ;&lt;br /&gt;&lt;br /&gt;  signature ( &lt;: ) : Self -&gt; Self -&gt; basics#bool ;&lt;br /&gt;  property mem_incl : all s1 s2 : Self,&lt;br /&gt;                      s1 &lt;: s2 &lt;-&gt; all v : Val, v &lt;&lt; s1 -&gt; v &lt;&lt; s2 ;&lt;br /&gt;  theorem incl_refl : all s : Self, s &lt;: s&lt;br /&gt;    proof = by property mem_incl ;&lt;br /&gt;  theorem incl_tran : all s1 s2 s3 : Self,&lt;br /&gt;                      s1 &lt;: s2 -&gt; s2 &lt;: s3 -&gt; s1 &lt;: s3&lt;br /&gt;    proof = by property mem_incl ;&lt;br /&gt;&lt;br /&gt;  theorem incl_empty : all s : Self, empty &lt;: s&lt;br /&gt;    proof = by property mem_incl, mem_empty ;&lt;br /&gt;  theorem incl_insert : all s : Self, all v : Val, s &lt;: s + v&lt;br /&gt;    proof = by property mem_insert, mem_incl ;&lt;br /&gt;  theorem incl_remove : all s : Self, all v : Val, s - v &lt;: s&lt;br /&gt;    proof = by property mem_remove, mem_incl ;&lt;br /&gt;&lt;br /&gt;  let ( = ) (s1, s2) = if (s1 &lt;: s2) then (s2 &lt;: s1) else false ;&lt;br /&gt;&lt;br /&gt;  property mem_congr : all v1 v2 : Val, Val!( = ) (v1, v2) -&gt;&lt;br /&gt;                       (all s : Self, (v1 &lt;&lt; s) &lt;-&gt; (v2 &lt;&lt; s)) ;&lt;br /&gt;&lt;br /&gt;  theorem incl_insert_mem : all s : Self, all v : Val,&lt;br /&gt;                            v &lt;&lt; s -&gt; s + v &lt;: s&lt;br /&gt;    proof = by property mem_congr, mem_insert, mem_incl ;&lt;br /&gt;end ;;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;　この次には、自動証明が失敗するケースを扱います。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-250990580170034694?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/250990580170034694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=250990580170034694' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/250990580170034694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/250990580170034694'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/05/coq-focalize-tutorial-1.html' title='[Coq] FoCaLize Tutorial (1)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8402541888585520328</id><published>2010-05-07T00:06:00.002+09:00</published><updated>2010-05-07T00:22:28.067+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] ASN.1 Library is under construction</title><content type='html'>　この連休にCoqの練習がてら作っていたASN.1のライブラリで、全然完成してないのだがとりあえず出来たところまで公開。&lt;br /&gt;　Coqdocで生成したドキュメントが&lt;a href="http://homepage.mac.com/takashi_miyamoto/coq/TLV.html"&gt;TLV.html&lt;/a&gt;です。（コードが成長したら随時更新予定）&lt;br /&gt;&lt;br /&gt;　ASN.1が何かについては、&lt;a href="http://luca.ntop.org/Teaching/Appunti/asn1.html"&gt;A Layman's Guide to a Subset of ASN.1, BER, and DER&lt;/a&gt;あたりを読んで下さい。電子証明書とかで使っているバイナリフォーマットなので、証明付きのライブラリを作りたいのだ。&lt;br /&gt;&lt;br /&gt;　本当は&lt;pre&gt;Inductive tlv_value : Set := &lt;br /&gt;| Primitive : string -&gt; tlv_value &lt;br /&gt;| Structured : list tlv -&gt; tlv_value&lt;br /&gt;.&lt;/pre&gt;みたいに定義したかったのだが、そうするとtlv_value, tlv に関する帰納法をうまく構成出来なかった。まだCPDT Chapter 3の読み込みが足りないのだろうなぁ。&lt;br /&gt;　が、とりあえず幾つかの定理も証明できたし、出だしとしてはこんなものかもとも思う。&lt;br /&gt;&lt;br /&gt;　Coqを勉強しようと思う様なプログラマの人は、ある程度複雑な型（相互再帰的だったり再帰がネストしていたり）を定義出来ると思うが、Coqは帰納型に対して帰納法を与える関数が作れないと駄目で、しかしそこが実は難しい、というのがこの連休に得た知見だ。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8402541888585520328?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8402541888585520328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8402541888585520328' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8402541888585520328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8402541888585520328'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/05/coq-asn1-library-is-under-construction.html' title='[Coq] ASN.1 Library is under construction'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3591415975257155517</id><published>2010-05-05T10:45:00.004+09:00</published><updated>2010-05-07T00:57:03.008+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] How to use Record</title><content type='html'>　Coq で Record を使う方法を調べました。基本的には記述を簡単にする構文糖のようです。これを使うと、事前条件を満たす証明を要求するコンストラクタを簡単に書けます。&lt;br /&gt;　使い方は下記の例を見てもらうのが簡単でしょう。&lt;br /&gt;&lt;br /&gt;　まず正の有理数を表すRat型を作りたいと考えます。符号は無視するとして、分母が０で無いことを保証したい、分子分母が既約である事を保証したい、とします。こんな感じに書けます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Record Rat : Set := mkRat {&lt;br /&gt;  numer : nat;&lt;br /&gt;  denom : nat;&lt;br /&gt;  denom_not_zero : denom &lt;&gt; O;&lt;br /&gt;  irreducible : forall g n d:nat, &lt;br /&gt;    (mult g n)=numer /\ (mult g d)=denom -&gt; g = S O&lt;br /&gt;}.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ratで 1/2 を定義したい時はこんな感じになります。まず補題を証明しないと値を作れません。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Lemma two_not_zero : 2 &lt;&gt; 0.&lt;br /&gt;Proof.&lt;br /&gt;  discriminate.&lt;br /&gt;Qed.&lt;br /&gt;Lemma one_two_irred : forall g n d:nat, (mult g n)=1 /\ (mult g d)=2 -&gt; g = S O.&lt;br /&gt;Admitted. (* 証明省略 *)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;こうして初めて値を作れます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Definition half : Rat := mkRat 1 2 two_not_zero one_two_irred.&lt;br /&gt;Print half. (* mkRat 1 2 two_not_zero one_two_irred : Rat *)&lt;br /&gt;Eval compute in (numer half). (* 1 : nat *)&lt;br /&gt;Eval compute in (denom_not_zero half). (* two_not_zero *)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;アクセサに見えるnumerなどは単なる関数です、従って同じ名前空間でnumerを他に定義出来ません。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Print numer.&lt;br /&gt;numer = &lt;br /&gt;fun r : Rat =&gt; let (numer, denom, _, _) := r in numer&lt;br /&gt;     : Rat -&gt; nat&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ratに関する帰納法は下記の様になります。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Print Rat_ind.&lt;br /&gt;(* forall P : Rat -&gt; Prop,&lt;br /&gt;       (forall (numer denom : nat) (denom_not_zero : denom &lt;&gt; 0)&lt;br /&gt;          (irreducible : forall g n d : nat,&lt;br /&gt;                         g * n = numer /\ g * d = denom -&gt; g = 1),&lt;br /&gt;        P (mkRat numer denom denom_not_zero irreducible)) -&gt;&lt;br /&gt;       forall r : Rat, P r *)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3591415975257155517?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3591415975257155517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3591415975257155517' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3591415975257155517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3591415975257155517'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/05/coq-how-to-use-record.html' title='[Coq] How to use Record'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3851100230376612262</id><published>2010-05-03T13:38:00.002+09:00</published><updated>2010-05-03T14:58:25.734+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><category scheme='http://www.blogger.com/atom/ns#' term='Alloy'/><title type='text'>[Alloy][FM] Sample code: Addressbook</title><content type='html'>　&lt;a href="http://study-func-prog.blogspot.com/2010/05/coqfm-fomal-methods-forum-4.html"&gt;[Coq][FM] Fomal Methods Forum #4&lt;/a&gt;でのAlloyチュートリアルの話。&lt;br /&gt;&lt;br /&gt;　まず Alloy4 を各自インストールしておくのは前提。但し、JARファイル１つなので、JRE (Java5以上) が入っているコンピュータならば起動は難しくありません。&lt;br /&gt;&lt;br /&gt;　表示されるWindowの左側入力欄に下記を打ち込みます。&lt;pre&gt;&lt;br /&gt;sig Name, Addr {}&lt;br /&gt;sig Book {&lt;br /&gt;  addr: Name -&gt; lone Addr&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;　&lt;code&gt;sig&lt;/code&gt;というのは普通のOO言語のクラス定義の様なもの --- なんですが、Alloy はOOなプログラミング言語ではないのでOOとのアナロジーは時に誤解を与えるかも。どちらかというと、RDBMSに Name, Addr という表を作ったと考えるといいかも。実際、Alloy は関係代数に基づいていますし。&lt;br /&gt;　OO でいうところのインスタンスはAlloyではatomと言います。Alloyでインスタンスというのは、全てのatomから構成されるモデル（モデルの中には求める反例とかも含まれます）のことを指します。用語は間違わない様に。&lt;br /&gt;　また、&lt;code&gt;.&lt;/code&gt; (ドット演算子) もOO言語の属性やメソッドを指す様に勘違いしますが、join演算子で、RDBのjoinみたいな振る舞いをします。&lt;br /&gt;　Bookのatomを仮に B0, B1 と書くと、Book は {(B0), (B1)} という集合です。（ () はタプル、{}は集合を表す。）&lt;br /&gt;&lt;br /&gt;　lone は 0 or 1 個を表す数量限定子です。他にも all (全ての)、some (１個以上)、one (１個)、no (０個) があります。lone Addr は、関数型言語的には Option Addrのようなものです。&lt;br /&gt;　addr は Book の属性みたいに見えますが、これも関数型言語的には addr : Book -&gt; Name -&gt; Option Addr -&gt; Prop みたいに考えると良いです。addr は (Book, Name, Addr) のタプル型の元の集合、例えば{(B0,N0,D0), (B1,N1,D1)}として表現されます。 （関係 R : R x y は (X,Y) の部分集合として表現出来る）&lt;br /&gt;　Book = {(B0),(B1)} であると、ドットはjoin演算子なので（テンソルとかの添字の縮約の如く）ジョイン演算をします。Bookとaddrの共通のB0を見て(B0).(B0,N0,D1)=(N0,D0)の様に計算して、b=B0ならば、b.addr={(N0,D0)}, Book.addr={(N0,D0),(N1,D1)} となります。&lt;br /&gt;&lt;br /&gt;　この時点で sig Book {...} の下に&lt;pre&gt;&lt;br /&gt;pred show[] {}&lt;br /&gt;run show for 3&lt;br /&gt;&lt;/pre&gt;と書いて Execute のボタンを押します。&lt;br /&gt;　右側に Instance found と出るので Instance のリンクを押すと、atom 間の関係を示すダイヤグラムが表示されます。nextを押すと別のインスタンスが表示されます。&lt;br /&gt;　for 3 と書いたので各 sig 毎に 3 atom づつです。&lt;br /&gt;&lt;br /&gt;　次にモデルの性質をテストする事を考えます。addr を追加して削除すると元に戻る、という性質が成り立つ事をモデル検査で確認（＝反例が見つからない事を確認）します。&lt;br /&gt;　まず追加と削除を表す述語を定義します。述語なので戻り値は真偽値を返します。&lt;pre&gt;&lt;br /&gt;pred add[disj b,b':Book, n:Name, a:Addr] {&lt;br /&gt;  b'.addr = b.addr + (n -&gt; a)&lt;br /&gt;}&lt;br /&gt;pred del[disj b,b':Book, n:Name] {&lt;br /&gt;  b'.addr = b.addr - (n -&gt; Addr)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;　Alloyは手続き型言語ではないので、b'addrに何か破壊的代入が行われる事は無く、単にbとb'の間の関係を示しているだけです。disjはbとb'とが別atomであるという意味です。&lt;br /&gt;&lt;br /&gt;　次いでテストしたい性質を書きます。&lt;pre&gt;&lt;br /&gt;assert delUndoesAdd {&lt;br /&gt;  all b,b',b'':Book, n:Name, a:Addr |&lt;br /&gt;    add[b,b',n,a] and del[b',b'',n] implies b.addr = b''.addr&lt;br /&gt;}&lt;br /&gt;check delUndoesAdd for 5&lt;br /&gt;&lt;/pre&gt;　&lt;code&gt;|&lt;/code&gt;はsuch thatみたいな意味、and, implisは論理演算の記号です。&lt;br /&gt;&lt;br /&gt;　これを追加してexecuteすると「何故か」counterexampleが見つかったと表示されます。counterexampleをじっと眺めると、bとb'が同じBookであることが判ります。&lt;br /&gt;　これは元々 b に (n -&gt; a) が含まれていた場合、b, b' が同じになるからです。（集合に既にある要素を加えても同じ）&lt;br /&gt;　assertの中身を&lt;pre&gt;&lt;br /&gt;    no n.(b.addr) and add[b,b',n,a] and del[b',b'',n] implies b.addr = b''.addr&lt;br /&gt;&lt;/pre&gt;に修正するとconterexampleが無くなります。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3851100230376612262?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3851100230376612262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3851100230376612262' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3851100230376612262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3851100230376612262'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/05/alloyfm-sample-code-addressbook.html' title='[Alloy][FM] Sample code: Addressbook'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2993551964917354488</id><published>2010-05-02T10:26:00.002+09:00</published><updated>2010-05-02T11:10:29.242+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq][FM] Fomal Methods Forum #4</title><content type='html'>　4/29に&lt;a href="http://atnd.org/events/4110"&gt;第4回FormalMethods勉強会&lt;/a&gt;を行いました。&lt;br /&gt;&lt;br /&gt;　今回は&lt;br /&gt;Alloy&lt;br /&gt;　Alloyの教科書の例題（アドレス帳）を元に文法を勉強しました。大体文法は把握出来たかな。&lt;br /&gt;　あとは自分で使ってみるべきなんだろうが、あまりモデリングとか仕事でやらないしなぁ。とりあえずパズルをAlloyで解く練習をするかなぁ。&lt;br /&gt;&lt;br /&gt;CEGAR&lt;br /&gt;　今回はCEGARという手法の話を聞きました。CEGARはCounterExample-Guided Abstraction Refinementの略で、モデル検査における状態数爆発を抑える為の一手法です。&lt;br /&gt;　モデル検査で扱う検査の中に、到達可能性解析（エラー状態などの特定の状態にと到達するか否かの解析）があります。&lt;br /&gt;　状態数を抑える方法としてモデルの抽象化（モデルの粗視化）があります。抽象化によって、エラー状態に遷移する可能性のある状態と、到達しない状態とが同一視されてしまうと、本当はエラー状態に到達しないにも関わらず、エラー状態に達すると誤って判定されます。&lt;br /&gt;　CEGARは、エラー状態に到達する解に対して、解析（最弱事前条件？）を行って抽象化を修正（状態を分割）して再解析する手法です。エラー状態に達した場合にはそれが本当に達したのか、抽象化を改善して再度解析を実施します。&lt;br /&gt;　原理だけ聞くと、当たり前の話と思えるのですが、実際に自動化するところを実装するのは難しそうというか見当が付かない。&lt;br /&gt;&lt;br /&gt;Coq&lt;br /&gt;　Coqは&lt;a href="http://adam.chlipala.net/cpdt/cpdt.pdf "&gt;Certified Programming with Dependent Type&lt;/a&gt;のChapter 1,2をざっと流して、Chapter 3を3.3まで読み終わりました。&lt;br /&gt;　当日使用した資料 (PPT, Coqファイル) については&lt;a href="http://groups.google.co.jp/group/fm-forum/msg/e5c0fb1994ac2460"&gt;Googleグループ上の記事&lt;/a&gt;にリンクを纏めましたので、そちらから辿って下さい。&lt;br /&gt;　本当はChapter 3を終わりたかったのですが終わらなかったのはちょっと残念でした。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2993551964917354488?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2993551964917354488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2993551964917354488' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2993551964917354488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2993551964917354488'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/05/coqfm-fomal-methods-forum-4.html' title='[Coq][FM] Fomal Methods Forum #4'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8760985261628052842</id><published>2010-04-26T21:49:00.002+09:00</published><updated>2010-04-26T22:05:57.583+09:00</updated><title type='text'>[Coq] Tail-recursive reverse</title><content type='html'>　先の&lt;a href="http://study-func-prog.blogspot.com/2010/04/coq-reverse-reverse-xs-xs.html"&gt;reverse (reverse xs) = xs&lt;/a&gt;で示した reverse は末尾再帰でなく、効率の悪い定義である。&lt;br /&gt;　そこで末尾再帰な&lt;br /&gt;&lt;pre&gt;Fixpoint rev' {A:Set} (xs ys:list A) :=&lt;br /&gt; match xs with&lt;br /&gt; | nil =&gt; ys&lt;br /&gt; | cons x xs' =&gt; rev' xs' (cons x ys)&lt;br /&gt; end.&lt;br /&gt;Definition rev {A:Set} (xs:list A) :=&lt;br /&gt; rev' xs nil.&lt;br /&gt;Eval compute in rev (cons 1 (cons 2 (cons 3 nil))).&lt;/pre&gt;&lt;br /&gt;について&lt;br /&gt;&lt;pre&gt;Theorem reverse_rev : forall (A:Set) (xs:list A),&lt;br /&gt; reverse xs = rev xs.&lt;/pre&gt;&lt;br /&gt;が成り立つ事を示そう。まず補題&lt;br /&gt;&lt;pre&gt;Lemma rev'_reverse : forall (A:Set) (xs ys:list A),&lt;br /&gt; rev' xs ys = reverse xs ++ ys.&lt;br /&gt;Proof.&lt;br /&gt; intros A xs.&lt;br /&gt; induction xs; simpl.&lt;br /&gt;   intro. reflexivity.&lt;br /&gt; intro ys'.&lt;br /&gt; rewrite (IHxs (cons a ys')).&lt;br /&gt; (* reverse xs ++ cons a ys' =&lt;br /&gt;    (reverse xs ++ cons a nil) ++ ys' *)&lt;br /&gt; assert (H: cons a ys' = (cons a nil) ++ ys').&lt;br /&gt; induction ys'; simpl.&lt;br /&gt;   reflexivity.&lt;br /&gt; reflexivity.&lt;br /&gt; rewrite H.&lt;br /&gt; rewrite (append_assoc A (reverse xs) (cons a nil) ys').&lt;br /&gt; reflexivity.&lt;br /&gt;Qed.&lt;/pre&gt;&lt;br /&gt;である。証明の冒頭で intros A xs だけを行い、ysについては intro していないが、ys を残したまま xs の帰納法を行わないと、IHxs を apply するときにうまくいかない。「無闇に intro しない方が良い」という良い例なので、ys を一緒に intros してしまうなど自分で試行錯誤してみて欲しい。&lt;br /&gt;&lt;br /&gt;　この補題を使えば、&lt;br /&gt;&lt;pre&gt;Theorem reverse_rev : forall (A:Set) (xs:list A),&lt;br /&gt; reverse xs = rev xs.&lt;br /&gt;Proof.&lt;br /&gt; intros.&lt;br /&gt; unfold rev.&lt;br /&gt; induction xs; simpl.&lt;br /&gt;   reflexivity.&lt;br /&gt; (* reverse xs ++ cons a nil = rev' xs (cons a nil) *)&lt;br /&gt; rewrite IHxs.&lt;br /&gt; (* rev' xs nil ++ cons a nil = rev' xs (cons a nil) *)&lt;br /&gt; rewrite (rev'_reverse A xs nil).&lt;br /&gt; rewrite (rev'_reverse A xs (cons a nil)).&lt;br /&gt; assert (H: forall l:list A, l ++ nil = l).&lt;br /&gt;   induction l; simpl.&lt;br /&gt;     reflexivity.&lt;br /&gt;   rewrite IHl.  reflexivity.&lt;br /&gt; rewrite (H (reverse xs)).&lt;br /&gt; reflexivity.&lt;br /&gt;Qed.&lt;/pre&gt;&lt;br /&gt;と証明出来る。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8760985261628052842?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8760985261628052842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8760985261628052842' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8760985261628052842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8760985261628052842'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/04/coq-tail-recursive-reverse.html' title='[Coq] Tail-recursive reverse'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5637002420316294512</id><published>2010-04-26T20:36:00.003+09:00</published><updated>2010-04-26T21:48:53.851+09:00</updated><title type='text'>[Coq] reverse (reverse xs) = xs</title><content type='html'>　&lt;a href="http://study-func-prog.blogspot.com/2010/04/coq-proof-cafe-01.html"&gt;先日のProofCafe&lt;/a&gt;でみんなで解いていた reverse (reverse xs) = xs の証明について、どんな風に解くかを解説というか自分の解答を晒すというか。&lt;br /&gt;&lt;br /&gt;　教科書でこの問題を演習課題として解く場合は、予め必要な補題が順々に証明課題として与えられる事が多いが、現実の問題ではそういうことはまず無い。（このあたり、現実の問題と試験問題の違いにも通ずる話だ。）&lt;br /&gt;&lt;br /&gt;　まず、&lt;a href="http://www.itpl.co.jp/ocaml-nagoya/index.php?ProofCafe01"&gt;ProofCafe01&lt;/a&gt;から必要な定義をコピーしよう。&lt;br /&gt;&lt;pre&gt;Inductive list (A: Type) : Type :=&lt;br /&gt; | nil  : list A&lt;br /&gt; | cons : A -&gt; list A -&gt; list A.&lt;br /&gt;&lt;br /&gt;Implicit Arguments nil [A].&lt;br /&gt;Implicit Arguments cons [A].&lt;br /&gt;&lt;br /&gt;Fixpoint append {A : Type} (xs ys: list A) : list A :=&lt;br /&gt; match xs with&lt;br /&gt; | nil =&gt; ys&lt;br /&gt; | cons x xs =&gt; cons x (append xs ys)&lt;br /&gt; end.&lt;br /&gt;Infix "++" := append (at level 60).&lt;br /&gt;&lt;br /&gt;Theorem append_assoc : forall (A:Type) (xs ys zs:list A),&lt;br /&gt; (xs ++ ys) ++ zs = xs ++ (ys ++ zs).&lt;br /&gt;Proof.&lt;br /&gt; (* あなたの証明を書いてね *)&lt;br /&gt;Qed.&lt;/pre&gt;&lt;br /&gt;定理append_assocの証明は難しく無いと思うが、判らない人はProofCafeのページを参照して欲しい。&lt;br /&gt;&lt;br /&gt;　次いで、関数reverseを定義しよう。&lt;br /&gt;　関数型言語で関数を末尾再帰で書くのに慣れている人は、ついうっかり&lt;br /&gt;&lt;pre&gt;Fixpoint rev' {A:Set} (xs ys:list A) :=&lt;br /&gt; match xs with&lt;br /&gt; | nil =&gt; ys&lt;br /&gt; | cons x xs' =&gt; rev' xs' (cons x ys)&lt;br /&gt; end.&lt;br /&gt;Definition rev {A:Set} (xs:list A) := rev' xs nil.&lt;/pre&gt;&lt;br /&gt;と書いてしまうだろう。私も実は当日そう書いてしまい嵌った。&lt;br /&gt;&lt;br /&gt;　ここは実行効率を考えず、ひとまず素直に、&lt;br /&gt;&lt;pre&gt;Fixpoint reverse {A:Set} (xs:list A) :=&lt;br /&gt;match xs with&lt;br /&gt;| nil =&gt; nil&lt;br /&gt;| cons x xs' =&gt; (reverse xs') ++ (cons x nil)&lt;br /&gt;end.&lt;/pre&gt;&lt;br /&gt;と定義して証明する方が簡単だ。関数を実際に動かしてみる場合は、&lt;br /&gt;&lt;pre&gt;Eval compute in reverse (cons 1 (cons 2 (cons 3 nil))).&lt;/pre&gt;&lt;br /&gt;とか入力してみれば良い。&lt;br /&gt;&lt;br /&gt;　ここから、どうやって証明していったか、考えた過程を示そう。&lt;br /&gt;　まずはいきなり、定理を証明しようとしてみた。&lt;br /&gt;&lt;pre&gt;Theorem reverse_reverse : forall (A:Set) (xs:list A),&lt;br /&gt;  reverse (reverse xs) = xs.&lt;br /&gt;Proof.&lt;br /&gt;  induction xs; simpl.&lt;br /&gt;    reflexivity.&lt;/pre&gt;&lt;br /&gt;最初にxsについての帰納法を試み、&lt;code&gt;xs=nil&lt;/code&gt;のケースは簡単に証明出来た。次のゴールの&lt;br /&gt;&lt;code&gt;reverse (reverse xs ++ (cons a nil) = cons a xs&lt;/code&gt;&lt;br /&gt;については、リストを ++ で繋いでreverseする、&lt;br /&gt;&lt;code&gt;Hypothesis reverse_append : forall (A:Set) (xs ys:list A),&lt;br /&gt; reverse (xs ++ ys) = (reverse ys) ++ (reverse xs).&lt;/code&gt;&lt;br /&gt;という定理があれば都合が良さそうだと何となく思いつく。（なんとなく美しげな定理だし。）&lt;br /&gt;&lt;br /&gt;　そこで、とりあえず上記のHypothesisを先に定義して、改めてreverse_reverseを証明する。&lt;br /&gt;&lt;pre&gt;Theorem reverse_reverse : forall (A:Set) (xs:list A),&lt;br /&gt; reverse (reverse xs) = xs.&lt;br /&gt;Proof.&lt;br /&gt;  induction xs; simpl.&lt;br /&gt;    reflexivity.&lt;br /&gt;  rewrite (reverse_append A (reverse xs) (cons a nil)).&lt;br /&gt;  rewrite IHxs.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;　この時点でゴールが&lt;br /&gt;&lt;code&gt;reverse (cons a nil) ++ xs = cons a xs&lt;/code&gt;&lt;br /&gt;となる。そこで再度&lt;br /&gt;&lt;pre&gt;Hypothesis append_cons_nil : forall (A:Set) (a:A) (xs:list A),&lt;br /&gt; (cons a nil) ++ xs = cons a xs.&lt;br /&gt;Hypothesis reverse_cons : forall (A:Set) (a:A),&lt;br /&gt; reverse (cons a nil) = cons a nil.&lt;/pre&gt;&lt;br /&gt;を追加してから、改めてreverse_reverseを証明する。&lt;br /&gt;&lt;pre&gt;Theorem reverse_reverse : forall (A:Set) (xs:list A),&lt;br /&gt; reverse (reverse xs) = xs.&lt;br /&gt;Proof.&lt;br /&gt;  induction xs; simpl.&lt;br /&gt;    reflexivity.&lt;br /&gt;  rewrite (reverse_append A (reverse xs) (cons a nil)).&lt;br /&gt;  rewrite IHxs.&lt;br /&gt;  rewrite (reverse_cons A a).&lt;br /&gt;  rewrite (append_cons_nil A a xs).&lt;br /&gt;  reflexivity.&lt;br /&gt;Qed.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;　証明が出来たので、Hypothesisで誤摩化していた部分をLemma, Theoremに書き換えて証明する。&lt;br /&gt;&lt;pre&gt;Lemma append_cons_nil : forall (A:Set) (a:A) (xs:list A),&lt;br /&gt; (cons a nil) ++ xs = cons a xs.&lt;br /&gt;Lemma reverse_cons : forall (A:Set) (a:A),&lt;br /&gt; reverse (cons a nil) = cons a nil.&lt;/pre&gt;&lt;br /&gt;については難しく無いので証明してみると良いだろう。(intros, simpl, reflexivityで証明出来る。)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Theorem reverse_append : forall (A:Set) (xs ys:list A),&lt;br /&gt; reverse (xs ++ ys) = (reverse ys) ++ (reverse xs).&lt;/pre&gt;&lt;br /&gt;については、解説しよう。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Proof.&lt;br /&gt; intros A xs ys.&lt;br /&gt; induction xs; simpl.&lt;br /&gt;   assert (append_nil: forall (zs:list A), zs = zs ++ nil).&lt;br /&gt;     induction zs; simpl.&lt;br /&gt;       reflexivity.&lt;br /&gt;     rewrite &lt;- IHzs.  reflexivity.&lt;br /&gt;   apply (append_nil (reverse ys)).&lt;br /&gt; rewrite IHxs.&lt;br /&gt; rewrite (append_assoc A (reverse ys) (reverse xs) (cons a nil)).&lt;br /&gt; reflexivity.&lt;br /&gt;Qed.&lt;/pre&gt;&lt;br /&gt;証明の途中で&lt;code&gt;zs = zs ++ nil&lt;/code&gt;が使いたくなり、わざわざ補題にするまでもないと思って、途中でassertで証明している。&lt;br /&gt;　この証明したreverse_appendを使って、reverse_reverseを証明すれば完成。&lt;br /&gt;&lt;br /&gt;　全体を改めて示すとこのようになる。&lt;br /&gt;&lt;pre&gt;Inductive list (A: Type) : Type :=&lt;br /&gt;| nil : list A&lt;br /&gt;| cons : A -&gt; list A -&gt; list A.&lt;br /&gt;&lt;br /&gt;Implicit Arguments nil [A].&lt;br /&gt;Implicit Arguments cons [A].&lt;br /&gt;&lt;br /&gt;Fixpoint append {A : Type} (xs ys: list A) : list A :=&lt;br /&gt;match xs with&lt;br /&gt;| nil =&gt; ys&lt;br /&gt;| cons x xs =&gt; cons x (append xs ys)&lt;br /&gt;end.&lt;br /&gt;Infix "++" := append (at level 60).&lt;br /&gt;&lt;br /&gt;Theorem append_assoc : forall (A: Type) (xs ys zs : list A),&lt;br /&gt;(xs ++ ys) ++ zs = xs ++ (ys ++ zs).&lt;br /&gt;Proof.&lt;br /&gt;  intros.&lt;br /&gt;  induction xs; simpl.&lt;br /&gt;    reflexivity.&lt;br /&gt;  rewrite IHxs.  reflexivity.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Fixpoint reverse {A:Set} (xs:list A) :=&lt;br /&gt;match xs with&lt;br /&gt;| nil =&gt; nil&lt;br /&gt;| cons x xs' =&gt; (reverse xs') ++ (cons x nil)&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;Lemma append_cons_nil : forall (A:Set) (a:A) (xs:list A),&lt;br /&gt; (cons a nil) ++ xs = cons a xs.&lt;br /&gt;Proof.&lt;br /&gt;  intros. simpl. reflexivity.&lt;br /&gt;Qed.&lt;br /&gt;Lemma reverse_cons : forall (A:Set) (a:A),&lt;br /&gt; reverse (cons a nil) = cons a nil.&lt;br /&gt;Proof.&lt;br /&gt;  intros. simpl. reflexivity.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Theorem reverse_append : forall (A:Set) (xs ys:list A),&lt;br /&gt; reverse (xs ++ ys) = (reverse ys) ++ (reverse xs).&lt;br /&gt;Proof.&lt;br /&gt; intros A xs ys.&lt;br /&gt; induction xs; simpl.&lt;br /&gt;   assert (append_nil: forall (zs:list A), zs = zs ++ nil).&lt;br /&gt;     induction zs; simpl.&lt;br /&gt;       reflexivity.&lt;br /&gt;     rewrite &lt;- IHzs.  reflexivity.&lt;br /&gt;   apply (append_nil (reverse ys)).&lt;br /&gt; rewrite IHxs.&lt;br /&gt; rewrite (append_assoc A (reverse ys) (reverse xs) (cons a nil)).&lt;br /&gt; reflexivity.&lt;br /&gt;Qed.&lt;br /&gt;&lt;br /&gt;Theorem reverse_reverse : forall (A:Set) (xs:list A),&lt;br /&gt; reverse (reverse xs) = xs.&lt;br /&gt;Proof.&lt;br /&gt;  induction xs; simpl.&lt;br /&gt;    reflexivity.&lt;br /&gt;  rewrite (reverse_append A (reverse xs) (cons a nil)).&lt;br /&gt;  rewrite IHxs.&lt;br /&gt;  rewrite (reverse_cons A a).&lt;br /&gt;  rewrite (append_cons_nil A a xs).&lt;br /&gt;  reflexivity.&lt;br /&gt;Qed.&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5637002420316294512?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5637002420316294512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5637002420316294512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5637002420316294512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5637002420316294512'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/04/coq-reverse-reverse-xs-xs.html' title='[Coq] reverse (reverse xs) = xs'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8724530457993226372</id><published>2010-04-26T01:30:00.003+09:00</published><updated>2010-04-26T01:47:01.751+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Proof Cafe #01</title><content type='html'>&lt;a href="http://atnd.org/events/3867"&gt;Proof Cafe (栄)&lt;/a&gt;に参加しました。&lt;br /&gt;&lt;br /&gt;　当日使われた資料は&lt;a href="http://coq.g.hatena.ne.jp/yoshihiro503/20100331"&gt;yoshihiro503の日記&lt;/a&gt;を参照の事。&lt;br /&gt;&lt;br /&gt;　yoshihiro503さんによるCoq最速文法マスターという感じで、僅か90分の入門講座で、（Haskellなど関数型言語の知識があるとはいえ）Coqに初めての人が&lt;br /&gt;&lt;code&gt;Theorem append_length : forall (A: Type) (xs ys: list A),&lt;br /&gt;  length (xs ++ ys) = length xs + length ys.&lt;/code&gt;&lt;br /&gt;を証明出来る様になるってのは、やはり説明の手際が良いよなぁ。次に入門用PPTを修正する時は是非とも参考にしよう。&lt;br /&gt;&lt;br /&gt;　Proof Cafe自体は２時間だったんですが、その後、懇親会を実施して頂き、なんか身に余る様な歓待をして頂きました。皆さんどうもありがとうございました。Coqに限らず関数型言語とかIT業界の話とか色々楽しく話をしました。&lt;br /&gt;&lt;br /&gt;　Proof Cafeは今後も毎月名古屋で開催されるとか、Proof CafeでもCPDTを読もうとしている、ようです。&lt;a href="http://groups.google.co.jp/group/fm-forum"&gt;Formal Methods Forum&lt;/a&gt;の方でも頑張ってCPDTを読んでいきたいです。&lt;br /&gt;&lt;br /&gt;　&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8724530457993226372?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8724530457993226372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8724530457993226372' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8724530457993226372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8724530457993226372'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/04/coq-proof-cafe-01.html' title='[Coq] Proof Cafe #01'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2923901010071676307</id><published>2010-04-18T22:52:00.003+09:00</published><updated>2010-04-18T22:56:39.751+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Install on NetWalker</title><content type='html'>　買ってあったがしばらく放置していたNetWalkerにCoq, CoqIDEをインストールしました。まぁUbuntuなんで、sudo apt-get install coq coqideでインストール出来て当然だが、なんかCoqのバージョンが古いみたい。&lt;br /&gt;　ともあれ通勤途中にCoqで遊べる様になった。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2923901010071676307?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2923901010071676307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2923901010071676307' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2923901010071676307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2923901010071676307'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/04/coq-install-on-netwalker.html' title='[Coq] Install on NetWalker'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-427877050845233511</id><published>2010-04-17T20:45:00.003+09:00</published><updated>2010-04-17T20:51:36.808+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq][FM] Formal Methods Forum #4 on 4/29</title><content type='html'>　形式仕様に関する勉強会の&lt;a href="http://atnd.org/events/4110"&gt;ATND - 第4回FormalMethods勉強会&lt;/a&gt;を4/29に行います。&lt;br /&gt;　Coqに関しては&lt;a href="http://adam.chlipala.net/cpdt/cpdt.pdf"&gt;Certi􏰀ed Programming with Dependent Types&lt;/a&gt;という教科書を今回から読み進める予定です。この本は、関数型言語のプログラマ向けに書かれた割と実践的な教科書です。&lt;br /&gt;　Coq以外の内容についてはATNDのページからFormal Methods Forumのページを辿って下さい。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-427877050845233511?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/427877050845233511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=427877050845233511' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/427877050845233511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/427877050845233511'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/04/coqfm-formal-methods-forum-4-on-429.html' title='[Coq][FM] Formal Methods Forum #4 on 4/29'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3102430204658159301</id><published>2010-04-17T20:26:00.003+09:00</published><updated>2010-04-26T22:31:52.235+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>[Haskell] Haskellers Meeting 2010 Spring</title><content type='html'>&lt;a href="http://atnd.org/events/3820"&gt;Haskellers Meeting 2010 Spring&lt;/a&gt;を聞きにいきました。&lt;br /&gt;&lt;br /&gt;　和田先生の話は、まぁ割とどうでも良い昔話だった。&lt;br /&gt;　メインはSimon Peyton JonesさんのSTMの話。基本的には"Beautiful Code"に載っている話で、ジョークなども比較的聞き取りやすかった。ScalaにもSTM早く欲しいなぁ。&lt;br /&gt;　山本さんのHaskellでWebサーバの話は前に聞いたことのある話だった。&lt;br /&gt;　山下さんの擬データの話が、実は一番興味深かった。紹介された論文「擬データを用いた対話的関数プログラミングに関する研究」（石井裕一郎）はWeb上で見つからなかったが、「擬データと関数による並行プロセス群の記述」は検索するとCiNii上で読める様だ。擬データは興味深いのだけど、Haskell以外の言語では意味が無いかなぁ。&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;追記：&lt;br /&gt;&lt;a href="http://d.hatena.ne.jp/nobsun/20100426"&gt;山下さんの発表資料はここから入手可能。&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3102430204658159301?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3102430204658159301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3102430204658159301' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3102430204658159301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3102430204658159301'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/04/haskell-haskellers-meeting-2010-spring.html' title='[Haskell] Haskellers Meeting 2010 Spring'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2286955135278457470</id><published>2010-04-03T21:52:00.003+09:00</published><updated>2010-04-03T21:57:39.583+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq][FM] Formal Methods Forum Meeting #3</title><content type='html'>一見、キャンセル待ち状況になっている&lt;a href="http://atnd.org/events/3687"&gt;第3回FormalMethods勉強会&lt;/a&gt;ですが、まぁ椅子を追加して対応可能だと思うので、とりあえず名前をATNDに書いて下さい。&lt;br /&gt;&lt;br /&gt;あと、直前に案内メールとかが流れますので&lt;a href="http://groups.google.co.jp/group/fm-forum"&gt;FormalMethods勉強会のGoogle group&lt;/a&gt;にも登録して頂くと良いと思います。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2286955135278457470?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2286955135278457470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2286955135278457470' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2286955135278457470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2286955135278457470'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/04/coqfm-formal-methods-forum-meeting-3.html' title='[Coq][FM] Formal Methods Forum Meeting #3'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5804898739428246032</id><published>2010-03-28T03:00:00.003+09:00</published><updated>2010-03-28T03:11:01.586+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq Course Materials at Nagoya Univ.</title><content type='html'>　&lt;a href="http://www.math.nagoya-u.ac.jp/~garrigue/lecture/2009_AW/"&gt;名古屋大学の2009年度後期のGarrigue先生のCoqの講義&lt;/a&gt;の教材が公開されているので、Coqの勉強として解いてみた。&lt;br /&gt;　全部は自力では解けず、答えを参照しつつ解いた部分もある。自習用には良い教材だと思った。&lt;br /&gt;　解答とかcoqdocでHTML化したんだけど...宿題は公開するとまずいよね、やはり。2009年度後期はまだ終わってないし。&lt;br /&gt;　とりあえず&lt;a href="http://groups.google.co.jp/group/fm-forum"&gt;Formal Methods Forum&lt;/a&gt;の勉強会用に使えるかな？&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5804898739428246032?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5804898739428246032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5804898739428246032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5804898739428246032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5804898739428246032'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/03/coq-coq-course-materials-at-nagoya-univ.html' title='[Coq] Coq Course Materials at Nagoya Univ.'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2682938304788366793</id><published>2010-02-28T23:44:00.002+09:00</published><updated>2010-02-28T23:46:29.596+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Joke'/><title type='text'>[Joke] How do you trap a programmer in the shower?</title><content type='html'>redditの&lt;a href="http://www.reddit.com/r/programming/comments/b2ma8/how_do_you_trap_a_programmer_in_the_shower/"&gt;How do you trap a programmer in the shower? (list.cs.brown.edu)&lt;/a&gt;経由。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2010-February/038167.html"&gt;[plt-scheme] OT: How do you trap a programmer in the shower?&lt;/a&gt;を翻訳してみました。&lt;br /&gt;&lt;br /&gt;オチが判らなかった箇所が幾つかあって、それはつまり誤訳してる可能性が高いので、間違っていたら指摘して頂けると嬉しいです。&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;ある生徒が教室で１つ目のジョークを言い、この類にはもっと色々考えられる様な気がした。これは最初の試みなので批判や追加を歓迎する。代名詞の性別についてはご容赦を。男性と女性を入れ替えたりすべきかどうか自信が無いし、彼/彼女と書くのは変だし、複数形で書くと複数人でシャワーを浴びている様なニュアンスがでてしまって本意じゃないし。:-)&lt;br /&gt;&lt;br /&gt;Todd&lt;br /&gt;&lt;br /&gt;Schemeプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;シャンプーを一瓶渡せ。(Hand him a bottle of shampoo.)&lt;br /&gt;&lt;br /&gt;Visual Basicプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;カーテンをオープンするウィジェットを隠せ。&lt;br /&gt;&lt;br /&gt;BASICプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;彼のCommodore-64をタイルに固定する為にシリコン接着剤を使え。&lt;br /&gt;&lt;br /&gt;アセンブラプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;えーと、まず彼はシャワーをビルドしないと。&lt;br /&gt;&lt;br /&gt;Javaプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;どこかにexitShower()メソッドがあると彼を説得し、ドキュメント全体を精査し終わるまで笑ってやれ。&lt;br /&gt;&lt;br /&gt;Pythonプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;Guidoがそこにいることを望んでいると彼に伝えろ。&lt;br /&gt;&lt;br /&gt;Cプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;そんなことをするな。彼は風呂桶をオーバーフローさせて君の家のコントロールを奪うだろう。&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;以下はredditで追加された物を幾つかピックアップして紹介。&lt;br /&gt;&lt;br /&gt;C#プログラマをシャワー室に閉じ込めるには？&lt;br /&gt;&gt; インテリセンスをオフにしろ。&lt;br /&gt;&lt;br /&gt;PHPプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;1. その頃、PHPプログラマは芝生に裸で立ち、庭用ホースと驚く程沢山のアタッチメントを手にして、どうして他の全ての人がシャワーの方が良いと言っているのか理解出来ない。&lt;br /&gt;2. PHPプログラマをシャワーの外に出そうとしても出来ない。全ての現実の仕事はシャワーの中でだけ起き、外でのことは単にアカデミックでエリートぶった連中のすることだと主張するだろう。&lt;br /&gt;3. 必要ない。ドキュメントをチェックしないと呼ぶべきメソッドがopen_door(), door_open(), openDoor(), doorOpen() のどれなのか思い出せないから。&lt;br /&gt;&lt;br /&gt;LISPプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;1. 冗談を。LISPプログラマはシャワーを浴びない。(don't _take_ showers : 副作用が無いという話？)&lt;br /&gt;2. ")"キーを奪え。&lt;br /&gt;&lt;br /&gt;Rubyプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;彼が中に入ったらCurtain#openメソッドにモンキーパッチを当てろ。追加で一つ引数を取る様にして、その引数が何なのかドキュメントに書いておかない。&lt;br /&gt;&gt; 彼は単に引数が不要になるモンキーパッチを当てて戻すだけだが、そのパッチは一回以上使うとsegfaultする様な代物だ。&lt;br /&gt;&lt;br /&gt;Prologプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;1. Yes (ってオチが良く解らん)&lt;br /&gt;2. inShower(Programmer) :- inShower(Programmer).&lt;br /&gt;&lt;br /&gt;Haskellプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;1. &lt; 圏論に関する馬鹿馬鹿しい程に長い小論を挿入せよ &gt;&lt;br /&gt;2. 何もする必要が無い。シャワーの水で洗って純粋になったならば、シャワーから出るには出力が必要だと気付くから。&lt;br /&gt;3. 必要ない。彼は怠惰(lazy)なので外に出ない。&lt;br /&gt;&lt;br /&gt;JavaScriptプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;1. 気にする必要は無い。同時に２つのシャワーは動作しないので、それを修正しようと時間を費やすから。&lt;br /&gt;2. IE6のロゴをシャワーカーテンに張ってデバッグする様に頼め。&lt;br /&gt;&lt;br /&gt;Erlangプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;出来ない。彼は自分自身をクローンして、別々のシャワーで全てのクローンに身体の別々の部位を洗わせる。もし閉じ込められたら単にそれを殺すだけだ。&lt;br /&gt;&lt;br /&gt;C++プログラマをシャワー室に閉じ込めるには？&lt;br /&gt;C++プログラマはシャワーをvoidポインタにキャストして、ドアの存在を消す。&lt;br /&gt;&gt; 「これは正しいやり方ではないがしかし...」という注釈を付けるのを忘れてるよ。&lt;br /&gt;&lt;br /&gt;Perlプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;1. 彼はどうやったら自分のシャワーが動くのか思い出せない。&lt;br /&gt;2. 彼の脱出用の針金の余りで、閉じたシャワーカーテンとシャワーの向きを固定しているダクトテープとをくっ付けておく。&lt;br /&gt;&lt;br /&gt;Objective-Cプログラマをシャワー室に閉じ込めるには？&lt;br /&gt;[[NSShower standardShower] addPerson:[NSObjectiveCProgrammer programmerWithRSI]];&lt;br /&gt;SEL removeSelector = @selector(removePerson:);&lt;br /&gt;Method removeMethod = class_getInstanceMethod([NSShower class], removeSelector);&lt;br /&gt;removeMethod-&gt;method_imp = voidMethod;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2682938304788366793?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2682938304788366793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2682938304788366793' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2682938304788366793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2682938304788366793'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/02/joke-how-do-you-trap-programmer-in.html' title='[Joke] How do you trap a programmer in the shower?'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8898458351287362507</id><published>2010-02-14T10:50:00.005+09:00</published><updated>2010-02-14T11:06:13.515+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FM'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq][FM] Formal Methods Forum #1</title><content type='html'>　2010/02/08に&lt;a href="http://atnd.org/events/2968"&gt;第1回FormalMethods勉強会&lt;/a&gt;というのがありました。&lt;br /&gt;　形式手法って、企業内の勉強会とか、あるいは有料の研修コースはあるのだけど (i.e. ビジネスになる、ということなんだろう)、無料のIT勉強会はほとんどありませんでした。&lt;br /&gt;　「形式手法の勉強会欲しいよね〜」という話から勉強会を始めることになり、まず第１回は各自の持ちネタを持ち寄る感じで開催されました。&lt;br /&gt;　私はCoqとWhy (INRIAで作っているプログラムの検証用ツール) の話をしました。&lt;a href="http://www.slideshare.net/tmiya/coq-20100208a"&gt;発表資料をSlideshareに上げた&lt;/a&gt;ので興味のある方はどうぞ。&lt;br /&gt;&lt;br /&gt;　Coqに限らず、形式仕様記述 (B, Zとか)、あるいは各種モデル検査 (SPIN, Alloyとか)、Lightweight Formal Method (VDMとか) なんでもありの勉強会なので興味のある方はどうぞ。&lt;br /&gt;　開催場所は新宿の豆蔵オフィスを利用させて頂く事が多いのではないかと思うが、Coqという意味では一度名古屋遠征したいなぁ。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://groups.google.co.jp/group/fm-forum/"&gt;Formal Methods Forum&lt;/a&gt; : 勉強会のGoogle group&lt;br /&gt;&lt;a href="http://www39.atwiki.jp/fm-forum/"&gt;fm-forum @ ウィキ&lt;/a&gt; : 勉強会のWiki&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8898458351287362507?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8898458351287362507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8898458351287362507' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8898458351287362507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8898458351287362507'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/02/coqfm-formal-methods-forum-1.html' title='[Coq][FM] Formal Methods Forum #1'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2362720645417704706</id><published>2010-02-11T02:45:00.002+09:00</published><updated>2010-02-11T02:55:29.591+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Articles about Scala 2.8 on ITpro</title><content type='html'>　Scala 2.8に関する紹介記事をITproに書きました。ほぼ年末年始休暇を費やして書き、2010年の1,2月に分けて掲載。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://itpro.nikkeibp.co.jp/article/COLUMN/20100113/343144/?ST=develop"&gt;第15回 Scala 2.8の新機能 (1)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://itpro.nikkeibp.co.jp/article/COLUMN/20100204/344207/?ST=develop"&gt;第16回 Scala 2.8の新機能 (2) --- コレクションライブラリの再実装&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;　記事を書く機会を与えてくださった羽生田さんに感謝を。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2362720645417704706?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2362720645417704706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2362720645417704706' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2362720645417704706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2362720645417704706'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/02/scala-articles-about-scala-28-on-itpro.html' title='[Scala] Articles about Scala 2.8 on ITpro'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-5127841011171021701</id><published>2010-01-31T18:29:00.003+09:00</published><updated>2010-02-01T01:50:35.732+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Hindley-Milner Type Inference</title><content type='html'>Hindley-Milnerの型推論を理解したいと思い、とりあえず&lt;a href="http://www.scala-lang.org/docu/files/ScalaByExample.pdf"&gt;Scala by Example&lt;/a&gt;に載っているコードにデバッグプリントを大量に挿入して動かしてみました。&lt;br /&gt;動かした結果を、将来の自分の為にメモしたものが&lt;a href="http://homepage.mac.com/takashi_miyamoto/scala/HM.pdf"&gt;HM.pdf&lt;/a&gt;、&lt;br /&gt;動かしたソースは&lt;a href="http://homepage.mac.com/takashi_miyamoto/scala/HM.scala"&gt;HM.scala&lt;/a&gt;にあります。&lt;br /&gt;&lt;br /&gt;アルゴリズム自体は&lt;a href="http://www.ii.uib.no/~bezem/INF121/hm.ps"&gt;Hindley Milner Type Inference Algorithm (PS file)&lt;/a&gt;とか簡潔に書かれている。が、こうやってデバッグプリントを挟んで動かしてみないとなかなか判らない...。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5127841011171021701?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/5127841011171021701/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=5127841011171021701' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5127841011171021701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/5127841011171021701'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2010/01/scala-hindley-milner-type-inference.html' title='[Scala] Hindley-Milner Type Inference'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3336825410540872641</id><published>2009-12-17T12:00:00.003+09:00</published><updated>2009-12-17T12:11:41.183+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Talk on scala-be's "Step by Step Scala" on 12/22</title><content type='html'>　東京のScala勉強会である&lt;a href="http://groups.google.co.jp/group/scala-be/"&gt;scale-be&lt;/a&gt;の、12/22開催の&lt;a href="http://atnd.org/events/2563"&gt;Step by Step Scala [vol.06]@scala-be (ATNDへのリンク)&lt;/a&gt;で講師をすることになりました。&lt;br /&gt;　今回は主として14章の「表明と単体テスト」のScalaCheckの使い方を中心に話をしようと思っています。ScalaCheckは「満たすべき性質を記述する」ことでテストケースを自動生成してくれる面白い単体テストツールですが、従来のxUnit系テストツールとはちょっと使い方が違うというのもあって、使い方を学ぶには良いのではないかと思います。&lt;br /&gt;　参加者希望者は上記のATNDのリンクから申し込みをしていただければと思います。&lt;br /&gt;　今回は日程が12/22と多くの忘年会と重なる日で、割と参加者は少なそうでちょっと残念。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3336825410540872641?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3336825410540872641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3336825410540872641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3336825410540872641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3336825410540872641'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/12/scala-talk-on-scala-bes-step-by-step.html' title='[Scala] Talk on scala-be&apos;s &quot;Step by Step Scala&quot; on 12/22'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7894576042681333920</id><published>2009-11-29T22:44:00.002+09:00</published><updated>2009-11-29T23:02:25.123+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Scala Style Guide</title><content type='html'>&lt;a href="http://www.codecommit.com/scala-style-guide.pdf"&gt;Scala Style Guide&lt;/a&gt; (PDF)&lt;br /&gt;&lt;br /&gt;Scalaのコーディングスタイルガイド。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://old.nabble.com/-scala--Proposed-Style-Guide-to26310456.html#a26310456"&gt;[scala] Proposed Style Guide&lt;/a&gt;で議論されていて、Oderskyもコメントしてる。これが叩き台になって正式版が出たら訳すといいかなぁ。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7894576042681333920?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7894576042681333920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7894576042681333920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7894576042681333920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7894576042681333920'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/11/scala-scala-style-guide.html' title='[Scala] Scala Style Guide'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3055365388787472258</id><published>2009-11-23T11:36:00.002+09:00</published><updated>2009-11-23T11:52:31.257+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala][Book] Pro Scala: Monadic Design Patterns for the Web</title><content type='html'>APressから&lt;a href="http://www.apress.com/book/view/9781430228448"&gt;Pro Scala: Monadic Design Patterns for the Web&lt;/a&gt;という本が出る様です。&lt;br /&gt;今までの職業的プログラマの視野に入っていなかったが、実は実用的にも重要である概念の、&lt;br /&gt;- Monadic design patterns&lt;br /&gt;- Zippers and data type differentiation&lt;br /&gt;- Delimited continuations&lt;br /&gt;を考察するとのこと。&lt;br /&gt;&lt;br /&gt;「モナド＝デザインパターン」というのはあちこちで書かれていることだし、モナドに限らず圏論的視点で計算を考えようという話は&lt;a href="http://d.hatena.ne.jp/m-hiyama/"&gt;檜山さんのブログ&lt;/a&gt;で繰り返し出て来るテーマ（11/28開催のセミナーの&lt;a href="http://d.hatena.ne.jp/m-hiyama/20091119/1258609056"&gt;コパスタを食べる余会&lt;/a&gt;はまだ空席があるようですよ）。&lt;br /&gt;Delimited continuationということはScala 2.8対応だし、限定継続を一般向けに紹介した本は今までにあるのかなぁ？なんかそれだけでも価値があるよね。&lt;br /&gt;&lt;br /&gt;なんか非常に楽しみな本ですね。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3055365388787472258?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3055365388787472258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3055365388787472258' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3055365388787472258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3055365388787472258'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/11/scalabook-pro-scala-monadic-design.html' title='[Scala][Book] Pro Scala: Monadic Design Patterns for the Web'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2066099635146932579</id><published>2009-11-23T11:17:00.002+09:00</published><updated>2009-11-23T11:36:36.686+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Event'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Event] Recent Days</title><content type='html'>今週は、&lt;a href="http://atnd.org/events/2093"&gt;Step by Step Scala [vol.04]@scala-be&lt;/a&gt;で話をしたり、&lt;a href="http://hop.timedia.co.jp/show/Event"&gt;Haskellナイト&lt;/a&gt;を見に行ったり、&lt;a href="http://atnd.org/events/1627"&gt;Scala Hack-a-thon #1&lt;/a&gt;に参加したり、でした。&lt;br /&gt;&lt;br /&gt;Step-by-Step Scalaは、（少なくとも何人かの方には）Swarmについて興味を持ってもらえた様なので満足。この先の仕事の状況がまだ確定しないのだけど、また機会があればScalaの講師を出来ればなぁ、とか。&lt;br /&gt;&lt;br /&gt;Haskellナイトは、本の話がちょっと多過ぎたかなぁとは思うのだけど、出版合わせのイベントだから仕方がないのかなぁ。もうちょっとHaskellの話を聞きたかったかも。&lt;br /&gt;&lt;br /&gt;Scala Hackathonは存在を知った時には既に満員になっていて参加を諦めてたんですが、当日朝見たらキャンセルが大量に出たみたいで慌てて家を出た次第。yuroyoroさんの作成したテキストが良く出来ていて、みんな黙々とそれを読んでいたのかな？かつ、質問はtwitterで主として行われていたみたい。懇親会も楽しく参加させて頂きました。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2066099635146932579?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2066099635146932579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2066099635146932579' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2066099635146932579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2066099635146932579'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/11/event-recent-days.html' title='[Event] Recent Days'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-4013685404702905708</id><published>2009-10-25T21:17:00.004+09:00</published><updated>2009-11-21T10:49:06.702+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Talk on scala-be's "Step by Step Scala" in November</title><content type='html'>東京のScala勉強会に&lt;a href="http://groups.google.co.jp/group/scala-be"&gt;scale-be&lt;/a&gt;というのがありまして、隔週の水曜or木曜の夜に新宿の豆蔵で開催しています。&lt;br /&gt;内容はOderskyの「Scalaスケーラブルプログラミング」の章立てに沿って講師がScalaを解説するというもので、読書会の様にテキストに厳格に沿う訳ではありません。&lt;br /&gt;参加者は、&lt;ul&gt;&lt;br /&gt;&lt;li&gt;出来れば該当の本を持参して下さい。本の内容を逐一全部話す訳ではないですし。&lt;br /&gt;&lt;li&gt;出来れば最近のScala実行系（Scala 2.7系）がインストールされたノートPCを持参して下さい。簡単な課題とか、実際に自分でインタプリタ上で動作確認したり、などがあるので。同様に、Scala APIドキュメント（JavaDoc）などをインストールしておくと良いです。（なお、会場はコンセントは利用可能ですが、インターネット接続は提供されません。）&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;あと、勉強会の後に懇親会も行っています。&lt;br /&gt;&lt;br /&gt;で、11/4(Wed), 11/19(Thr)の２回は私が講師を担当する事になりました。それぞれ6,7章と8,9章の範囲について話す予定です。11/19の回にはテキストの内容からちょっと離れて最近のScalaの話題という事で&lt;a href="http://code.google.com/p/swarm-dpl/"&gt;Swarm&lt;/a&gt;の話をちょっとだけ紹介しようと思ってます。&lt;br /&gt;&lt;br /&gt;なお、参加申し込みはATND上で行われ、ATNDへのリンクを含む開催案内は定期的にscala-be上で告知されます。&lt;br /&gt;では、11月に勉強会会場でお会いしましょう。&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;追記：11/21&lt;br /&gt;&lt;br /&gt;２回の発表で使用した資料はPDF形式で&lt;a href="http://groups.google.co.jp/group/scala-be/files"&gt;scala-be Google groupのファイル置き場&lt;/a&gt;で公開してます。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-4013685404702905708?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/4013685404702905708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=4013685404702905708' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4013685404702905708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/4013685404702905708'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/10/scala-talk-on-scala-bes-step-by-step.html' title='[Scala] Talk on scala-be&apos;s &quot;Step by Step Scala&quot; in November'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7102720333278401455</id><published>2009-10-21T00:29:00.004+09:00</published><updated>2009-10-21T22:17:06.087+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agda'/><title type='text'>[Agda] Install Agda on Mac OS</title><content type='html'>Mac OS 10.5 の上にAgdaをインストールしました。基本的にはAgda Wikiを参考にしたのだけど、そのままではうまく動きませんでした。&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Xcodeをインストール。DVDからなり、ADCのサイトなりから。最新版は10.6用なので古いのをインストール。&lt;br /&gt;&lt;li&gt;Mac Portsのインストール。&lt;code&gt;/opt/local/bin&lt;/code&gt;に&lt;code&gt;PATH&lt;/code&gt;を通す。Mac Portsの準備が済んでいる人も&lt;code&gt;sudo port -v selfupdate&lt;/code&gt;する。&lt;br /&gt;&lt;li&gt;GHCはportsからインストールすると古くて駄目なので、&lt;a href="http://haskell.org/ghc/download%5Fghc%5F6%5F10%5F4.html#macosxintel"&gt;GHC download page&lt;/a&gt;よりバイナリパッケージを導入。&lt;br /&gt;&lt;li&gt;&lt;code&gt;sudo port install hs-cabal&lt;/code&gt;して、&lt;code&gt;sudo cabal update&lt;/code&gt;して、&lt;code&gt;~/.cabal/bin&lt;/code&gt;に&lt;code&gt;PATH&lt;/code&gt;を通す。&lt;br /&gt;&lt;li&gt;&lt;code&gt;sudo port install darcs&lt;/code&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;sudo cabal install happy&lt;/code&gt;して、&lt;code&gt;sudo cabal install alex&lt;/code&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;sudo cabal install Agda-executable&lt;/code&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;cd ~/.cabal/bin&lt;/code&gt;して、&lt;code&gt;./agda-mode setup&lt;/code&gt;&lt;br /&gt;&lt;li&gt;emacsは薦められるままにAquamacsを導入する。&lt;br /&gt;&lt;li&gt;下記を&lt;/code&gt;~/.emacs&lt;/code&gt;に追加。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;(setq load-path (cons "~/.cabal/share/Agda-2.2.4/emacs-mode/" load-path))&lt;br /&gt;(autoload 'agda2-mode "agda2-mode" "Major mode for Agda2 files" t)&lt;br /&gt;(unless (assoc "\\.agda" auto-mode-alist)&lt;br /&gt;   (setq auto-mode-alist&lt;br /&gt;   (nconc '(("\\.agda" . agda2-mode)&lt;br /&gt;     ("\\.alfa" . agda2-mode)) auto-mode-alist)))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;li&gt;Aquamacsを起動し、&lt;code&gt;~/test.agda&lt;/code&gt;というファイルを作成して、&lt;br /&gt;&lt;code&gt;&lt;br /&gt;module test where&lt;br /&gt;&lt;br /&gt;data Bool : Set where&lt;br /&gt;&amp;nbsp;&amp;nbsp;true  : Bool&lt;br /&gt;&amp;nbsp;&amp;nbsp;false : Bool&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;と書く（true, falseの前のインデント必須。単語や:の前後に空白があるのも確認。）&lt;br /&gt;&lt;code&gt;C-c C-l&lt;/code&gt;で入力内容が処理され、文字が色分けされたら、agda2-modeが動いている。&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;追記: &lt;code&gt;~/.emacs&lt;/code&gt;について念のため全部掲載。haskell-modeの設定も重要らしいので。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;(setq load-path (cons "‾/.cabal/share/Agda-2.2.4/emacs-mode/" load-path))&lt;br /&gt;(autoload 'agda2-mode "agda2-mode" "Major mode for Agda2 files" t)&lt;br /&gt;(unless (assoc "¥¥.agda" auto-mode-alist)&lt;br /&gt;   (setq auto-mode-alist&lt;br /&gt;   (nconc '(("¥¥.agda" . agda2-mode)&lt;br /&gt;     ("¥¥.alfa" . agda2-mode)) auto-mode-alist)))&lt;br /&gt;(setq load-path (cons "‾/lib/elisp/haskell" load-path))&lt;br /&gt;(setq auto-mode-alist&lt;br /&gt;      (append auto-mode-alist&lt;br /&gt;              '(("促促.[hg]s$"  . haskell-mode)&lt;br /&gt;                ("促促.hi$"     . haskell-mode)&lt;br /&gt;                ("促促.l[hg]s$" . literate-haskell-mode))))&lt;br /&gt;(autoload 'haskell-mode "haskell-mode"&lt;br /&gt;   "Major mode for editing Haskell scripts." t)&lt;br /&gt;(autoload 'literate-haskell-mode "haskell-mode"&lt;br /&gt;   "Major mode for editing literate Haskell scripts." t)&lt;br /&gt;(add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan)&lt;br /&gt;(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)&lt;br /&gt;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)&lt;br /&gt;(add-hook 'haskell-mode-hook 'turn-on-haskell-ghci)&lt;br /&gt;&lt;br /&gt;(setq haskell-literate-default 'latex)&lt;br /&gt;(setq haskell-doc-idle-delay 0)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(load-file (let ((coding-system-for-read 'utf-8))&lt;br /&gt;                (shell-command-to-string "agda-mode locate")))&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7102720333278401455?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7102720333278401455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7102720333278401455' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7102720333278401455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7102720333278401455'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/10/agda-install-agda-on-mac-os.html' title='[Agda] Install Agda on Mac OS'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-991062851684924661</id><published>2009-10-16T00:19:00.004+09:00</published><updated>2009-10-16T01:34:57.185+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agda'/><title type='text'>[Agda] Agda Lectures at CVS</title><content type='html'>産業技術総合研究所の&lt;a href="http://unit.aist.go.jp/cvs/training-course/Agda-course.html"&gt;研修コース「 Agda による仕様記述」&lt;/a&gt;に参加しました。&lt;br /&gt;&lt;br /&gt;以下は私の参加した10月の回の話。もしかしたら11月は10月の参加者の反応を見て内容が変更されるかもしれません。&lt;br /&gt;&lt;br /&gt;&lt;b&gt;一言で言うと&lt;/b&gt;&lt;br /&gt;Coq, Agda のような定理証明系とか依存型の関数型言語とかに興味のある人が、概要を知るには良い二日半のコース。参加費無料なのもポイントが高い。お薦め。（開催が大阪なんで関西周辺以外の人にはちょっと厳しいが）&lt;br /&gt;&lt;br /&gt;&lt;b&gt;もう少し詳しく説明すると&lt;/b&gt;&lt;br /&gt;「Agdaの持つ依存型の機能を使って、仕様の制約を型として表現すれば、機械的に検証出来るよね」というところに主眼を置いているみたいです。なので、定理証明の部分は従であり、主眼は仕様を書ける様になろう、ということのようです。&lt;br /&gt;とはいえ、仕様の制約をAgdaで書く以上、書いた関数が仕様を満たしていることを示す必要がある訳ですが...。&lt;br /&gt;&lt;br /&gt;が、まぁ当たり前と言えば当たり前なんですが、二日半ではAgdaを使いこなせるようにはならなかった...。まぁJavaだってHaskellだって二日半では使える様にはならない訳で、当然というか仕方が無い。なので、「Agdaがどんなものなのかの概説を聞く」ぐらいに考えていたほうが良いです。&lt;br /&gt;とはいえ、Agdaに関する日本語の資料はほとんど無い現状で、テキストの説明を聞き、判らないところを教わりつつのハンズオン実習がある訳で、価値は大きい。&lt;br /&gt;&lt;br /&gt;参加者は結局８名。堅苦しさの無い普通のIT系勉強会のようなフレンドリーな雰囲気で、質問しまくりみたいな。逆に言うと講義内容がまだきっちりと固まっている訳では無い感じです。&lt;br /&gt;&lt;a href="http://d.hatena.ne.jp/yoshihiro503/"&gt;にわとり小屋でのプログラミング日記&lt;/a&gt;のCoqな今井さんとお近づきになれたのも良かったです。数人で２日目の夜に懇親会したのですが、最初からちゃんと計画して全員（講師の方にも声をかけて）でやれば良かったと反省。&lt;br /&gt;＃話に出た紫色の本は、&lt;i&gt;"Handbook of Practical Logic and Automated Reasoning"&lt;/i&gt; (John Harrison, Cambridge Univ. Press, 2009) です＞今井さん。&lt;br /&gt;&lt;br /&gt;とにかく私は楽しかったです。代休消化で関西旅行した価値がありました。参加させて頂き、ありがとうございました＞CVSの方々。&lt;br /&gt;&lt;br /&gt;&lt;b&gt;参加の前提について&lt;/b&gt;&lt;br /&gt;募集要項には「プログラムを書いた経験(言語不問)、またはシステムやソフトウェアの設計に従事したことがあること。」「Emacs で文書を作成編集した経験があること。」と書いてあるんですが...。&lt;br /&gt;うーむ、HaskellとかOCamlとかの類の型付き関数型言語の初歩的な知識があったほうがいいかも。モナドとか別に知らなくてもいいけど、簡単な再帰とかパターンマッチとか使って List の map とか length とかぐらい書けたほうが良いかもしれないです。そうでないと初日の演習問題でいきなり困るかも。あとはまぁ、ペアノの自然数( 3 = succ(succ(succ(zero))) みたいな話 ) も知ってた方が良いかなぁ。&lt;br /&gt;ただ、参加者の関数型言語への習熟度を見て調整していたかも知れないので、11月はどうなるかは判らないです。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-991062851684924661?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/991062851684924661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=991062851684924661' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/991062851684924661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/991062851684924661'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/10/agda-agda-lectures-at-cvs.html' title='[Agda] Agda Lectures at CVS'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3808485646655237758</id><published>2009-07-25T12:11:00.004+09:00</published><updated>2009-07-25T23:42:52.137+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] sbt : simple-build-tool (1)</title><content type='html'>&lt;a href="http://code.google.com/p/simple-build-tool/"&gt;sbt (simple-build-tool)&lt;/a&gt; は Scala で書かれたビルドツールです。&lt;br /&gt;これもscalaで書かれたDSL的なツールであり、プロジェクトのビルドの設定などをscalaで記述する事が出来たりします。&lt;br /&gt;&lt;br /&gt;試しに使ってみて、使い方が判ったら追記していこうと思います。&lt;br /&gt;&lt;br /&gt;★インストール&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/simple-build-tool/wiki/Setup"&gt;Setup&lt;/a&gt;のページに従い作業します。&lt;br /&gt;私は MacOS ユーザなので Unix の指示に従い作業。&lt;br /&gt;&lt;br /&gt;まずsbt-launcher-0.5.1.jar をダウンロードして指示通り~/binに置き、~/bin/sbt ファイルを作り chmod したりします。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;% ls ~/bin&lt;br /&gt;sbt   sbt-launcher-0.5.1.jar&lt;br /&gt;% cat ~/bin/sbt&lt;br /&gt;java -Xmx256M -jar `dirname $0`/sbt-launcher-0.5.1.jar "$@"&lt;br /&gt;%&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;★動作確認&lt;br /&gt;空の (*.scala の無い) 作業ディレクトリに hw.scala を作ります。(main メソッドを探して自動で判断する都合上、無関係なソースがあると巧く動作しません。最初それで失敗しました。)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;% ls&lt;br /&gt;hw.scala&lt;br /&gt;% cat hw.scala&lt;br /&gt;object Hi { def main(args: Array[String]) { println("Hi!") } }&lt;br /&gt;% &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;とりあえず下記の様に動きました。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[apple-3:~/work/scala/hw] miyamoto% ~/bin/sbt &lt;br /&gt;Project does not exist, create new project? (y/N/s) : s&lt;br /&gt;:: loading settings :: url = jar:file:/Users/miyamoto/bin/sbt-launcher-0.5.1.jar!/org/apache/ivy/core/settings/ivysettings.xml&lt;br /&gt;:: retrieving :: sbt#boot&lt;br /&gt; confs: [default]&lt;br /&gt; 2 artifacts copied, 0 already retrieved (9831kB/149ms)&lt;br /&gt;:: retrieving :: sbt#boot&lt;br /&gt; confs: [default]&lt;br /&gt; 3 artifacts copied, 0 already retrieved (3171kB/26ms)&lt;br /&gt;[info] Building project scratch 1.0 using sbt.DefaultProject&lt;br /&gt;[info]    with sbt 0.5.1 and Scala 2.7.5&lt;br /&gt;[info] No actions specified, interactive session started. Execute 'help' for more information.&lt;br /&gt;&gt; run&lt;br /&gt;[info] &lt;br /&gt;[info] == compile ==&lt;br /&gt;[info]   Source analysis: 1 new/modified, 0 indirectly invalidated, 0 removed.&lt;br /&gt;[info] Compiling main sources...&lt;br /&gt;[info] Compilation successful.&lt;br /&gt;[info]   Post-analysis: 2 classes.&lt;br /&gt;[info] == compile ==&lt;br /&gt;[info] &lt;br /&gt;[info] == run ==&lt;br /&gt;[info] Running Hi ...&lt;br /&gt;Hi!&lt;br /&gt;[info] == run ==&lt;br /&gt;[success] Successful.&lt;br /&gt;[info] &lt;br /&gt;[info] Total time: 2 s&lt;br /&gt;&gt; quit&lt;br /&gt;[info] &lt;br /&gt;[info] Total session time: 14 s&lt;br /&gt;% &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;この結果として下記の様にプロジェクトが生成されます。このあたりは Maven とかと同様な感じ。各プロジェクト毎にscala-compiler.jarを持ったりするのは、なんか富豪的だなぁ。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;% ls -RCF&lt;br /&gt;hw.scala project/ target/&lt;br /&gt;&lt;br /&gt;./project:&lt;br /&gt;boot/   build.properties&lt;br /&gt;&lt;br /&gt;./project/boot:&lt;br /&gt;scala-2.7.5/&lt;br /&gt;&lt;br /&gt;./project/boot/scala-2.7.5:&lt;br /&gt;lib/  sbt-0.5.1/ update.log&lt;br /&gt;&lt;br /&gt;./project/boot/scala-2.7.5/lib:&lt;br /&gt;scala-compiler.jar scala-library.jar&lt;br /&gt;&lt;br /&gt;./project/boot/scala-2.7.5/sbt-0.5.1:&lt;br /&gt;ivy-2.0.0.jar  jsch-0.1.31.jar  sbt_2.7.5-0.5.1.jar&lt;br /&gt;&lt;br /&gt;./target:&lt;br /&gt;analysis/ classes/&lt;br /&gt;&lt;br /&gt;./target/analysis:&lt;br /&gt;applications  external  hashes&lt;br /&gt;dependencies  generated_files  tests&lt;br /&gt;&lt;br /&gt;./target/classes:&lt;br /&gt;Hi$.class Hi.class&lt;br /&gt;% &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3808485646655237758?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3808485646655237758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3808485646655237758' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3808485646655237758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3808485646655237758'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/07/scala-sbt-simple-build-tool.html' title='[Scala] sbt : simple-build-tool (1)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3127650700775377878</id><published>2009-05-31T22:54:00.003+09:00</published><updated>2009-06-01T00:31:05.558+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] S-99: Ninety-Nine Scala Problems (P01-28)</title><content type='html'>&lt;a href="http://aperiodic.net/phil/scala/s-99/"&gt;S-99: Ninety-Nine Scala Problems&lt;/a&gt;のList編(P01-P28)の抄訳です。&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;アスタリスクの数は難易度です。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;効率も大事ですが、エレガントな回答を求めます。可能ならばより簡潔で、計算量が少なく、末尾再帰になっている回答を作りましょう。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Scalaの組み込み関数を使ってもOKです。が、使わないほうが勉強になります。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;答えが知りたければ、元の英語文書の各問題のリンクをクリックして下さい。&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;P01 (*) リストの最後の要素を求めよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; last(List(1, 1, 2, 3, 5, 8))&lt;br /&gt;res0: Int = 8&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P02 (*) リストの最後から二番目の要素を求めよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; penultimate(List(1, 1, 2, 3, 5, 8))&lt;br /&gt;res0: Int = 5&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P03 (*) リストのn番目の要素を求めよ。但しリストの最初の要素は0番目とする。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; nth(2, List(1, 1, 2, 3, 5, 8))&lt;br /&gt;res0: Int = 2&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P04 (*) リストの要素の数を求めよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; length(List(1, 1, 2, 3, 5, 8))&lt;br /&gt;res0: Int = 6&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P05 (*) リストを逆順にせよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; reverse(List(1, 1, 2, 3, 5, 8))&lt;br /&gt;res0: List[Int] = List(8, 5, 3, 2, 1, 1)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P06 (*) リストが回文になっているか調べよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; isPalindrome(List(1, 2, 3, 2, 1))&lt;br /&gt;res0: Boolean = true&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P07 (**) ネストされたリスト構造を平坦化せよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; flatten(List(List(1, 1), 2, List(3, List(5, 8))))&lt;br /&gt;res0: List[Any] = List(1, 1, 2, 3, 5, 8)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P08 (**) リスト要素の連続した重複物を除去せよ。もしリストの要素で繰り返し要素が含まれていたならば要素一つに置き換えよ。要素の順序は変えてはならない。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; compress(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))&lt;br /&gt;res0: List[Symbol] = List('a, 'b, 'c, 'a, 'd, 'e)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P09 (**) 連続した重複物を子リストに纏めよ。もしリストの要素が繰り返し要素ならば、別々の子リストに分割せよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; pack(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))&lt;br /&gt;res0: List[List[Symbol]] = List(List('a, 'a, 'a, 'a), List('b), List('c, 'c), List('a, 'a), List('d), List('e, 'e, 'e, 'e))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P10 (*) リストをランレングス・エンコードせよ。P09の結果を用いていわゆるランレングス・エンコーディングによるデータ圧縮法を実装せよ。連続した重複要素はタプル(N,E)にエンコードされる。但しNは要素Eの重複数。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; encode(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))&lt;br /&gt;res0: List[(Int, Symbol)] = List((4,'a), (1,'b), (2,'c), (2,'a), (1,'d), (4,'e))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P11 (*) 修正ランレングス・エンコーディング。P10の結果を修正し、もし要素に重複が無ければ単に要素を結果にコピーせよ。重複している要素だけを(N,E)の形に変換せよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; encodeModified(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))&lt;br /&gt;res0: List[Any] = List((4,'a), 'b, (2,'c), (2,'a), 'd, (4,'e))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P12 (**) ランレングス・エンコードされたリストをデコードせよ。P10の仕様で生成されたランレングス・エンコードされたリストを元の圧縮されていないものに戻せ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; decode(List((4, 'a), (1, 'b), (2, 'c), (2, 'a), (1, 'd), (4, 'e)))&lt;br /&gt;res0: List[Symbol] = List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P13 (**) リストのランレングス・エンコーディング（直接解法）。いわゆるランレングス・エンコーディングを直接実装せよ。すなわち（P09のpackの様な）自分で書いた他のメソッドを使ってはならない。直接書く事。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; encodeDirect(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))&lt;br /&gt;res0: List[(Int, Symbol)] = List((4,'a), (1,'b), (2,'c), (2,'a), (1,'d), (4,'e))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P14 (*) リスト要素を重複させよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt duplicate(List('a, 'b, 'c, 'c, 'd))&lt;br /&gt;res0: List[Symbol] = List('a, 'a, 'b, 'b, 'c, 'c, 'c, 'c, 'd, 'd)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P15 (**) 指定した個数、リスト要素を重複させよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; duplicateN(3, List('a, 'b, 'c, 'c, 'd))&lt;br /&gt;res0: List[Symbol] = List('a, 'a, 'a, 'b, 'b, 'b, 'c, 'c, 'c, 'c, 'c, 'c, 'd, 'd, 'd)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P16 (**) 毎N番目の要素を除去せよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; drop(3, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))&lt;br /&gt;res0: List[Symbol] = List('a, 'b, 'd, 'e, 'g, 'h, 'j, 'k)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P17 (*) リストを二つに分割せよ。前半の長さは与えられるものとする。結果はタプルで返す。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; split(3, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))&lt;br /&gt;res0: (List[Symbol], List[Symbol]) = (List('a, 'b, 'c),List('d, 'e, 'f, 'g, 'h, 'i, 'j, 'k))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P18 (**) リストのスライスを抽出せよ。二つの添字 i と j が与えられたとき、スライスとは元のリストの i 番目の要素を含むが j 番目の要素を含まないリストである。要素は0番目から始まるとする。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; slice(3, 7, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))&lt;br /&gt;res0: List[Symbol] = List('d, 'e, 'f, 'g)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P19 (**) リストの要素をn個左ローテートせよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; rotate(3, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))&lt;br /&gt;res0: List[Symbol] = List('d, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'a, 'b, 'c)&lt;br /&gt;&lt;br /&gt;scala&amp;gt; rotate(-2, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))&lt;br /&gt;res1: List[Symbol] = List('j, 'k, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P20 (*) リストのk番目の要素を除去せよ。除去されたリストと除去した要素をタプルで返せ。要素は0番目から始まるとする。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; removeAt(1, List('a, 'b, 'c, 'd))&lt;br /&gt;res0: (List[Symbol], Symbol) = (List('a, 'c, 'd),'b)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P21 (*) リストの指定された場所に要素を追加せよ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; insertAt('new, 1, List('a, 'b, 'c, 'd))&lt;br /&gt;res0: List[Symbol] = List('a, 'new, 'b, 'c, 'd)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P22 (*) 与えられた範囲の整数のリストを作れ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; range(4, 9)&lt;br /&gt;res0: List[Int] = List(4, 5, 6, 7, 8, 9)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P23 (**) リストから指定された数だけ値をランダムに選択せよ。（ヒント：P20を使え）&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; randomSelect(3, List('a, 'b, 'c, 'd, 'f, 'g, 'h))&lt;br /&gt;res0: List[Symbol] = List('e, 'd, 'a)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P24 (*) ロト：1〜Mからn個の異なるランダムな値を選べ。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; lotto(6, 49)&lt;br /&gt;res0: List[Int] = List(23, 1, 17, 33, 21, 37)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P25 (*) 要素のランダムな順列を作成せよ。（ヒント：P23を使え）&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; randomPermute(List('a, 'b, 'c, 'd, 'e, 'f))&lt;br /&gt;res0: List[Symbol] = List('b, 'a, 'd, 'c, 'e, 'f)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P26 (**) n要素数のリストからk個の異なるオブジェクトを取り出す組み合わせを生成せよ。12人から3人の委員会を作る方法は何通りだろうか？答えは C(12,3)=220通り（C(n,k）はよく知られた二項係数）である。数学者にとってはこれで十分であるが、我々は本当に全ての解を生成したい。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; combinations(3, List('a, 'b, 'c, 'd, 'e, 'f))&lt;br /&gt;res0: List[List[Symbol]] = List(List('a, 'b, 'c), List('a, 'b, 'd), List('a, 'b, 'e), ...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;P27 (**) 集合の要素を、互いに素な部分集合に纏めよ。&lt;br /&gt;a) 9人の人をそれぞれ2,3,4人の３グループに纏める方法は何通りか？全ての組み合わせを生成する関数を書け。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; group3(List("Aldo", "Beat", "Carla", "David", "Evi", "Flip", "Gary", "Hugo", "Ida"))&lt;br /&gt;res0: List[List[List[String]]] = List(List(List(Aldo, Beat), List(Carla, David, Evi), List(Flip, Gary, Hugo, Ida)), ...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;b) 上の問題を一般化してグループの大きさのリストを与えるとグループのリストを与える様にせよ。グループメンバーの順列は求めていない、すなわち((Aldo,Beat),...)は((Beat,Aldo),...)と同じ解である。しかし、((Aldo,Beat),(Carla,David),...)は((Carla,David),(Aldo,Beat),...)と異なる解である。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; group(List(2, 2, 5), List("Aldo", "Beat", "Carla", "David", "Evi", "Flip", "Gary", "Hugo", "Ida"))&lt;br /&gt;res0: List[List[List[String]]] = List(List(List(Aldo, Beat), List(Carla, David), List(Evi, Flip, Gary, Hugo, Ida)), ...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;この組み合わせ問題に関して知りたければ離散数学の良い本で「多項係数」について調べよ。&lt;br /&gt;P28 (**) リストのリストを長さでソートせよ。&lt;br /&gt;a) 要素がリストであるリストを考える。そのリストの要素を長さでソートする、すなわち短いリストを前に、長いリストを後にする。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; lsort(List(List('a, 'b, 'c), List('d, 'e), List('f, 'g, 'h), List('d, 'e), List('i, 'j, 'k, 'l), List('m, 'n), List('o)))&lt;br /&gt;res0: List[List[Symbol]] = List(List('o), List('d, 'e), List('d, 'e), List('m, 'n), List('a, 'b, 'c), List('f, 'g, 'h), List('i, 'j, 'k, 'l))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;b) 次に同様にリストを長さでソートするが、今回は長さの頻度でソートする。すなわち稀な長さのものを前に、頻度の高い長さのものを後ろにする。例の場合、長さ４と１のリストはただ１度しか現れない。3番目と4番目は長さ3のリスト２つである。最後に３つの最も頻度の高い長さ２のリストが現れる。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;scala&amp;gt; lsortFreq(List(List('a, 'b, 'c), List('d, 'e), List('f, 'g, 'h), List('d, 'e), List('i, 'j, 'k, 'l), List('m, 'n), List('o)))&lt;br /&gt;res1: List[List[Symbol]] = List(List('i, 'j, 'k, 'l), List('o), List('a, 'b, 'c), List('f, 'g, 'h), List('d, 'e), List('d, 'e), List('m, 'n))&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3127650700775377878?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3127650700775377878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3127650700775377878' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3127650700775377878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3127650700775377878'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/05/scala-s-99-ninety-nine-scala-problems.html' title='[Scala] S-99: Ninety-Nine Scala Problems (P01-28)'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8180908445500082768</id><published>2009-05-22T01:01:00.003+09:00</published><updated>2009-05-22T01:07:20.699+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Sudoku in Scala</title><content type='html'>&lt;a href="http://d.hatena.ne.jp/HHa/20090422/1240354191"&gt;Scalaユーザ会5/22(金)19：00-21：00@新宿三井ビル3&lt;/a&gt;で話をする予定の「Scalaで数独を解く」話です。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://homepage.mac.com/takashi_miyamoto/scala/ScalaSudoku.pdf"&gt;ScalaSudoku.pdf&lt;/a&gt; : プレゼン資料&lt;br /&gt;&lt;a href="http://homepage.mac.com/takashi_miyamoto/scala/Sudoku.scala"&gt;Sudoku.scala&lt;/a&gt; : ソースコード&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8180908445500082768?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8180908445500082768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8180908445500082768' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8180908445500082768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8180908445500082768'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/05/scala-sudoku-in-scala.html' title='[Scala] Sudoku in Scala'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-471727644236868582</id><published>2009-05-20T00:00:00.005+09:00</published><updated>2009-05-20T00:29:19.785+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Joke'/><title type='text'>[Joke] Translation of "A Brief, Incomplete, and Mostly Wrong History of Programming Languages"</title><content type='html'>&lt;a href="http://james-iry.blogspot.com/2009/05/brief-incomplete-and-mostly-wrong.html"&gt;A Brief, Incomplete, and Mostly Wrong History of Programming Languages&lt;/a&gt;の翻訳です。面白かったので翻訳してみました。&lt;br /&gt;&lt;br /&gt;&lt;b&gt;「簡潔で不完全でほとんど間違っているプログラミング言語の歴史」&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1801 - Joseph Marie Jacquardが、織機にパンチカードで命令することで、タペストリーに「hello, world」を織り込んだ。（しかし）末尾再帰やコンカレンシーの欠如、あるいは適切に大文字が使用されていないため、当時のRedditerたちは感銘を覚え無かった。&lt;br /&gt;&lt;br /&gt;1842 - Ada Lovelaceが最初のプログラムを書いた。その過程に於いて、コードを走らせる実際のコンピュータを持っていないという些細な困難に妨げられた。後のエンタープライズアーキテクトたちは、UMLでプログラムする為に、彼女のテクニックを再習得した。&lt;br /&gt;&lt;br /&gt;1936 - Alan Turingが、（将来に亘る）全てのプログラミング言語を発明した。しかし彼がその特許をとる前に、英国情報部は彼を007にするために強制徴募した。&lt;br /&gt;&lt;br /&gt;1936 - Alonzo Churchもまた、（将来に亘る）全てのプログラミング言語をさらにうまく発明した。彼のλ算法はC言語に十分似ていない為に無視された。この批判は、当時まだCが発明されていないという事実にも関わらず生じた。&lt;br /&gt;&lt;br /&gt;1940年代 - 結線とスイッチによって様々な「コンピュータ」が「プログラム」された。「タブ vs 空白」の論戦を避けるために、技術者たちはこの方式を採用した。&lt;br /&gt;&lt;br /&gt;1957 - John BackusとIBMがFORTRANを作った。IBMにもFORTRANにも面白いところは何も無い。青いネクタイを着用せずFORTRANを書くのは文法エラーである。&lt;br /&gt;&lt;br /&gt;1958 - John McCarthyとPaul GrahamがLISPを発明する。戦後の戦略的括弧備蓄の枯渇による高コストの為、LISPは決してポピュラーにはならなかった[1]。ポピュラーでは無いにも関わらず、LISP (今では "Lisp" あるいは時には "Arc") は「再帰と他人を見下すことなどの重要なアルゴリズム技法」に於ける影響度の高い言語であり続けている。&lt;br /&gt;&lt;br /&gt;1959 -  L. Ron Hubbardとの賭けに負けた後に、Grace Hopperを含む何人かのサディスト達が「大文字化された定型文志向言語」 (Capitalization Of Boilerplate Oriented Language = COBOL) を発明する。後に、Hooper提督のCOBOLの業績に対する見当外れで性差別的な報復として、Rubyコンファレンスでは嫌女性的題材が取り上げられる。&lt;br /&gt;&lt;br /&gt;1964 - John KemenyとThomas Kurtzが、非計算機科学者の為の非構造化プログラミング言語であるBASICを作った。&lt;br /&gt;&lt;br /&gt;1965 - KemenyとKurtzはGO TO 1964.&lt;br /&gt;&lt;br /&gt;1970 - Guy SteeleとGerald SussmanがSchemeを作った。彼らの著作は「Lambda the Ultimate」の一連の論文をもたらし、「究極の台所用品ラムダ」にその頂点を迎えた。この論文はロングランの基礎となったが、深夜のインフォマーシャルとしては究極的に失敗であった。Javaがラムダを持たないことによってラムダをポピュラーにするまでラムダは比較的目立たないところへと左遷された。&lt;br /&gt;&lt;br /&gt;1970 - Niklaus Wirthが手続き型言語のPascalを作った。Pascalは直ちに批難されたが、"x := x + y"という構文を、より親しみやすいC的な"x = x + y"の代わりに使用したためであった。この批判は、当時まだCが発明されていないという事実にも関わらず生じた。&lt;br /&gt;&lt;br /&gt;1972 - Dennis Ritchieは前後を同時に撃つことの出来る強力な銃を発明した。発明のもたらした多くの死者及び障害者に満足することなく、彼はCとUnixを発明した。&lt;br /&gt;&lt;br /&gt;1972 - Alain Colmerauerは論理型言語Prologをデザインした。彼の目標は二歳児の知性を持った言語を作ることであった。全てのクエリに「No」と答えるPrologセッションを示すことによって、目標に達したことを証明した。&lt;br /&gt;&lt;br /&gt;1973 - Robin MilnerはM&amp;M型理論に基づく言語のMLを作った。MLの子供として形式仕様意味論を持つSMLが生まれた。形式意味論の形式意味論を質問されてMilnerの頭は爆発した。ML一家の他の良く知られた言語にはOCaml, F#, Visual Basicがある。&lt;br /&gt;&lt;br /&gt;1980 - Alan kayはSmalltalkを作り、用語「オブジェクト指向」を発明した。その意味を聞かれると彼は「Smalltalkのプログラムは単にオブジェクトである」と答えた。オブジェクトは何から作られるのかを聞かれると彼は「オブジェクトだ」と答えた。再度質問されると彼は云った。「だからさ、下の下まで全部オブジェクトなんだってば。亀にたどり着くまでは。」&lt;br /&gt;&lt;br /&gt;1983 - Bjarne Stroustrupは耳にしたもの全てをCにねじ止めすることでC++を作った。その結果、言語は非常に複雑になり、プログラムをSkynet人工知能でコンパイルするために未来へ送らねばならなかった。ビルド時間は犠牲となった。Skynetがサービスを提供し続けた動機は依然としてはっきりしないが、未来からの広報担当はオーストリア訛りで単調に「気にするようなことは何も無い、ベイビー」と云った。Skynetはバッファーオーバーランを飾り立てたものに過ぎないという推測もある。&lt;br /&gt;&lt;br /&gt;1986 - Brad CoxとTom LoveがObjective-Cを作り、アナウンスした。「この言語はCのメモリ安全性とSmalltalkの素晴らしい実行速度が結びついたものです。」現代の歴史家たちは二人が失読症であったと疑っている。&lt;br /&gt;&lt;br /&gt;1987 - Larry Wallが眠気を催し、キーボードに額をぶつけた。目を覚ましたとき、Larry Wallのモニターの上の文字列はランダムなのではなく、神が預言者Larry Wallにデザインすることを欲しているプログラミング言語のサンプルプログラムだと悟った。Perlが生まれた。&lt;br /&gt;&lt;br /&gt;1990 - Simon Peyton-Jones, Paul Hudak, Philip Wadler, Ashton Kutcher そして「動物の倫理的扱いを求める人々の会」からなる委員会は、純粋非正格関数型言語Haskell を作った。副作用を制御するためモナドを使用する複雑さの為、Haskellは抵抗を受けた。Wadler は批判を和らげるために説明した。「モナドは自己準同系ファンクタの圏のモノイドなんだ。何か問題が？」&lt;br /&gt;&lt;br /&gt;1991 - オランダ人プログラマのGuido van Rossumが謎の手術の為にアルゼンチンへと旅行した。頭部に大きな傷を負って帰国し、Pythonを発明し、多数の賛同者によって終身独裁者に任じられ、世界に対して「あることをするのにひとつしかやり方がない」と報じた。ポーランドは神経質になっている。&lt;br /&gt;&lt;br /&gt;1995 - 「Mad Matz」こと、まつもとゆきひろは、漠然とした特定されない終末を避けるためにRubyを作ったが、その終末においてはオーストラリアはモヒカン戦士とティナ＝ターナーが支配する砂漠となる。その言語は後にRuby on Railsと、真の発明者David Heinemeier Hanssonによって改名された。[まつもとがRubyと呼ばれる言語を発明した云々は実際には起きておらず、この記事の次の改訂時に削除されるべきだ - DHH].&lt;br /&gt;&lt;br /&gt;1995 - Brendan Eichはプログラミング言語設計で起きた全ての失敗について読み、自分でも幾つか発明し、LiveScriptを作成した。後にその言語は、Javaの人気に肖る為、JavaScriptと改名された。後になっても、皮膚病の人気に肖る為にECMAScriptと改名された。&lt;br /&gt;&lt;br /&gt;1996 - James GoslingはJavaを発明した。Javaは比較的冗長で、ガベージコレクションをし、クラスベースで、静的型付けで、シングルディスパッチで、単一実装継承と複数インタフェース継承のオブジェクト指向な言語である。SunはJavaの新規性を宣伝した。&lt;br /&gt;&lt;br /&gt;2001 - Anders HejlsbergがC#を発明した。C#は比較的冗長で、ガベージコレクションをし、クラスベースで、静的型付けで、シングルディスパッチで、単一実装継承と複数インタフェース継承のオブジェクト指向の言語である。MicrosoftはC#の新規性を宣伝した。&lt;br /&gt;&lt;br /&gt;2003 - 酔っ払ったMartin Oderskyは誰かのピーナツバターが別の人のチョコレートにくっつくというReeseのピーナツバターカップのCMを見て着想を得た。彼はオブジェクト指向と関数型言語の作り上げたものを統合する言語Scalaを作った。これを見た両派閥とも激怒し、それぞれ直ちに聖戦を宣告した。&lt;br /&gt;&lt;br /&gt;Footnotes&lt;br /&gt;&lt;br /&gt;1. 計算機科学にとっては幸運なことに、中括弧と山括弧の供給は潤沢であった。&lt;br /&gt;2. &lt;a href="http://www.theregister.co.uk/2006/01/11/exception_handling/"&gt;Catch as catch can - Verity Stob&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-471727644236868582?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/471727644236868582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=471727644236868582' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/471727644236868582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/471727644236868582'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/05/joke-translation-of-brief-incomplete.html' title='[Joke] Translation of &quot;A Brief, Incomplete, and Mostly Wrong History of Programming Languages&quot;'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2217612096768929695</id><published>2009-05-03T22:33:00.003+09:00</published><updated>2009-05-03T23:07:22.330+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Jersey with Scala + Jetty</title><content type='html'>Jersey は JAX-RS (Java API for RESTful Web Service)のreference実装です。&lt;br /&gt;これをScalaで動かしてみます。&lt;br /&gt;&lt;br /&gt;1. Libraries : Jetty 6.1.17. Jersey 1.0.3 を使用しました。下記をEclipseプロジェクトのreference librariesに登録&lt;br /&gt;&lt;br /&gt;Jetty : jetty-XX.jar, jetty-util-XX.jar, servlet-api-XX.jar&lt;br /&gt;Jersey : jsr311-api-XX.jar, jersey-core-XX.jar, jersey-server-XX.jar, asm-XX.jar&lt;br /&gt;&lt;br /&gt;2. test.jersey.JerseyTest.scala : メインルーチンです&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test.jersey&lt;br /&gt;&lt;br /&gt;import javax.servlet.ServletException&lt;br /&gt;import javax.servlet.http.HttpServlet&lt;br /&gt;import javax.servlet.http.HttpServletRequest&lt;br /&gt;import javax.servlet.http.HttpServletResponse&lt;br /&gt;&lt;br /&gt;import org.mortbay.jetty.Server&lt;br /&gt;import org.mortbay.jetty.nio.SelectChannelConnector&lt;br /&gt;import org.mortbay.jetty.servlet.Context&lt;br /&gt;import org.mortbay.jetty.servlet.ServletHolder&lt;br /&gt;&lt;br /&gt;import com.sun.jersey.spi.container.servlet.ServletContainer&lt;br /&gt;  &lt;br /&gt;object JerseyTest {&lt;br /&gt;  def main(args: Array[String]) {&lt;br /&gt;    val server = new Server(8080)&lt;br /&gt;    val connector = new SelectChannelConnector()&lt;br /&gt;    server.addConnector(connector)&lt;br /&gt;    &lt;br /&gt;    val holder:ServletHolder = new ServletHolder(classOf[ServletContainer])&lt;br /&gt;    holder.setInitParameter(&lt;br /&gt;      "com.sun.jersey.config.property.resourceConfigClass",&lt;br /&gt;      "com.sun.jersey.api.core.PackagesResourceConfig")&lt;br /&gt;    holder.setInitParameter(&lt;br /&gt;      "com.sun.jersey.config.property.packages",&lt;br /&gt;      "test.jersey.resource")&lt;br /&gt;// URLをクラスにマッピングする為のpackage名&lt;br /&gt;&lt;br /&gt;    val context = new Context(server, "/", Context.SESSIONS)&lt;br /&gt;    context.addServlet(holder, "/*")&lt;br /&gt;    &lt;br /&gt;    server.start()&lt;br /&gt;    server.join()&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3. test.jersey.resource : /helloworld に対応するリソース&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test.jersey.resource&lt;br /&gt;&lt;br /&gt;import javax.ws.rs.GET&lt;br /&gt;import javax.ws.rs.Produces&lt;br /&gt;import javax.ws.rs.Path&lt;br /&gt;&lt;br /&gt;@Path("/helloworld")&lt;br /&gt;class HelloWorldResource {&lt;br /&gt;  @GET&lt;br /&gt;  @Produces(Array("text/plain"))&lt;br /&gt;  def getMessage:String = "Hello, World"&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4. テスト&lt;br /&gt;Eclipseでtest.jersey.JerseyTest をアプリケーションとして実行させます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;2009-05-03 22:56:18.064::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog&lt;br /&gt;2009-05-03 22:56:18.123::INFO:  jetty-6.1.17&lt;br /&gt;2009-05-03 22:56:18.205::INFO:  Started SocketConnector@0.0.0.0:8080&lt;br /&gt;2009-05-03 22:56:18.226::INFO:  Started SelectChannelConnector@0.0.0.0:55736&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;次いでアクセス&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;% telnet localhost 8080&lt;br /&gt;Trying 127.0.0.1...&lt;br /&gt;Connected to localhost.&lt;br /&gt;Escape character is '^]'.&lt;br /&gt;GET /helloworld HTTP/1.0&lt;br /&gt;&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;Content-Type: text/plain&lt;br /&gt;Server: Jetty(6.1.17)&lt;br /&gt;&lt;br /&gt;Hello, WorldConnection closed by foreign host.&lt;br /&gt;% &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;2009/05/03 22:57:08 com.sun.jersey.api.core.PackagesResourceConfig init&lt;br /&gt;情報: Scanning for root resource and provider classes in the packages:&lt;br /&gt;  test.jersey.resource&lt;br /&gt;2009/05/03 22:57:08 com.sun.jersey.api.core.PackagesResourceConfig init&lt;br /&gt;情報: Root resource classes found:&lt;br /&gt;  class test.jersey.resource.HelloWorldResource&lt;br /&gt;2009/05/03 22:57:08 com.sun.jersey.api.core.PackagesResourceConfig init&lt;br /&gt;情報: Provider classes found:&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2217612096768929695?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2217612096768929695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2217612096768929695' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2217612096768929695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2217612096768929695'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/05/scala-jersey-with-scala-jetty.html' title='[Scala] Jersey with Scala + Jetty'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-7291149821681353965</id><published>2009-05-03T02:21:00.003+09:00</published><updated>2009-05-03T02:38:14.455+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] Scala Servlet with Jetty6</title><content type='html'>Jetty + ScalaでServletを書いてみました。&lt;br /&gt;&lt;br /&gt;1. Projectの作成&lt;br /&gt;Eclipseで普通にScala Projectを作ります。&lt;br /&gt;ScalaServletという名前のScala Projectを作りました。&lt;br /&gt;&lt;br /&gt;2. Jetty6 の入手&lt;br /&gt;JettyのサイトからJetty6を入手します。私がダウンロードしたのはJetty 6.1.17でした。&lt;br /&gt;zipを解凍し、jetty-6.1.17.jar, jetty-util-6.1.17.jar, servlet-api-2.5-20081211.jar をプロジェクトにimportします。&lt;br /&gt;&lt;br /&gt;3. ソースを書く&lt;br /&gt;パッケージtest.jettyを作って、下記の様なJettyTest.scalaというファイルを作成します&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test.jetty&lt;br /&gt;&lt;br /&gt;import javax.servlet.ServletException&lt;br /&gt;import javax.servlet.http.HttpServlet&lt;br /&gt;import javax.servlet.http.HttpServletRequest&lt;br /&gt;import javax.servlet.http.HttpServletResponse&lt;br /&gt;&lt;br /&gt;import org.mortbay.jetty.Server&lt;br /&gt;import org.mortbay.jetty.nio.SelectChannelConnector&lt;br /&gt;import org.mortbay.jetty.servlet.ServletHandler&lt;br /&gt;&lt;br /&gt;object JettyTest {&lt;br /&gt;&lt;br /&gt;  def main(args: Array[String]) {&lt;br /&gt;    val server = new Server(8080)&lt;br /&gt;    val connector = new SelectChannelConnector()&lt;br /&gt;    server.addConnector(connector)&lt;br /&gt;    &lt;br /&gt;    val handler = new ServletHandler()&lt;br /&gt;    handler.addServletWithMapping(HelloServlet.getClass, "/")&lt;br /&gt;    server.addHandler(handler)&lt;br /&gt;  &lt;br /&gt;    server.start()&lt;br /&gt;    server.join()&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;object HelloServlet extends HttpServlet {&lt;br /&gt;  override def doGet(req:HttpServletRequest, resp:HttpServletResponse) {&lt;br /&gt;    val out = resp.getWriter&lt;br /&gt;    resp.setContentType("text/html")&lt;br /&gt;    out.println("&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;Hello, World!&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;")&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4.サーバ起動&lt;br /&gt;上記のJettyTest.scalaを普通にScala Applicationとして起動します。&lt;br /&gt;コンソールに下記の様に表示されます。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;2009-05-03 02:20:29.316::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog&lt;br /&gt;2009-05-03 02:20:29.358::INFO:  jetty-6.1.17&lt;br /&gt;2009-05-03 02:20:29.392::INFO:  Started SocketConnector@0.0.0.0:8080&lt;br /&gt;2009-05-03 02:20:29.413::INFO:  Started SelectChannelConnector@0.0.0.0:52134&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;5.アクセス&lt;br /&gt;ブラウザからhttp://localhost:8080/で確認してもOKですがコンソールから確認。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;% telnet localhost 8080&lt;br /&gt;Trying ::1...&lt;br /&gt;telnet: connect to address ::1: Connection refused&lt;br /&gt;Trying fe80::1...&lt;br /&gt;telnet: connect to address fe80::1: Connection refused&lt;br /&gt;Trying 127.0.0.1...&lt;br /&gt;Connected to localhost.&lt;br /&gt;Escape character is '^]'.&lt;br /&gt;GET / HTTP/1.0&lt;br /&gt;&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;Content-Type: text/html; charset=iso-8859-1&lt;br /&gt;Content-Length: 40&lt;br /&gt;Server: Jetty(6.1.17)&lt;br /&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;Hello, World!&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;Connection closed by foreign host.&lt;br /&gt;% &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7291149821681353965?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/7291149821681353965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=7291149821681353965' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7291149821681353965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/7291149821681353965'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/05/scala-scala-servlet-with-jetty6.html' title='[Scala] Scala Servlet with Jetty6'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8633399713375922860</id><published>2009-04-18T22:28:00.004+09:00</published><updated>2009-04-18T23:05:22.353+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Event'/><title type='text'>[Event] Type-Level Programming Meeting</title><content type='html'>&lt;a href="http://atnd.org/events/451"&gt;型レベルプログラミングの会&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;定員がすぐいっぱいになってしまって会場参加は出来ず、自宅からustreamで拝聴。&lt;br /&gt;発表された皆さん、どれも興味深い話でした。ありがとうございます。&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Scala : Scalaの型プログラミングの話は前にも聞かせて頂いたような気がするけど、更に話題が広がっていたような。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;C++ : 定番ではありながら、私はC++は経験が少ないので興味深く聞けました。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Haskell : フォロー出来ない話も多かったですが勉強になりました。勉強すべき事、多いなぁ。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;D : 型プログラミングの為のような言語ですね。興味深い。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;依存型プログラミング : プレゼン資料が大変面白いというか芸達者というか。April Foolの予告のGirardの逆理の話では無かった。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;G'Caml : 存在を始めて知りました。OCaml関係も色々あるなぁ。&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;この手の勉強会に参加すると、今まで知らなかったことがいっぱいあると判り、もっと勉強しなくちゃ、と思う。&lt;br /&gt;日々の仕事は非技術的な作業ばかりが増えているので、知的好奇心の刺激の為にもこの手の勉強会に積極的に参加しないと。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8633399713375922860?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8633399713375922860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8633399713375922860' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8633399713375922860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8633399713375922860'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/04/event-type-level-programming-meeting.html' title='[Event] Type-Level Programming Meeting'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3064288676757573633</id><published>2009-04-05T19:00:00.001+09:00</published><updated>2009-04-05T19:06:41.567+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq'Art Chap.2</title><content type='html'>Interactive Theorem Proving and Program Development; Coq'Art: The Calculus of Inductive Constructions の Chapter 2 です。&lt;br /&gt;&lt;br /&gt;この章では概ね次の４つが語られているように見えます。&lt;br /&gt;&lt;br /&gt;(1) Coq のコマンド&lt;br /&gt;&lt;br /&gt;下記の様なコマンドがあります。&lt;br /&gt;&lt;br /&gt;★&lt;code&gt;Require Import&lt;/code&gt; &lt;i&gt;library&lt;/i&gt;&lt;code&gt;.&lt;/code&gt;&lt;br /&gt;ライブラリをロードして environment に追加する。&lt;br /&gt;&lt;i&gt;library&lt;/i&gt;としては、&lt;code&gt;Arith, ZArith, Bool&lt;/code&gt;などがある。&lt;br /&gt;&lt;br /&gt;★&lt;code&gt;Open Scope&lt;/code&gt; &lt;i&gt;scope名&lt;/i&gt;&lt;code&gt;.&lt;/code&gt;&lt;br /&gt;Scope は notation を interprete する規則。例えば&lt;code&gt;Z_scope&lt;/code&gt;を指定すると各種演算子記号が Z の演算のものと判断される。&lt;br /&gt;&lt;br /&gt;★&lt;code&gt;Print Scope&lt;/code&gt; &lt;i&gt;scope名&lt;/i&gt;&lt;code&gt;.&lt;/code&gt;&lt;br /&gt;Scopeで定義された notation の一覧を得る。&lt;br /&gt;&lt;br /&gt;★&lt;code&gt;Check&lt;/code&gt; &lt;i&gt;term&lt;/i&gt;&lt;code&gt;.&lt;/code&gt;&lt;br /&gt;&lt;i&gt;term&lt;/i&gt;のtypeを表示させる。&lt;br /&gt;&lt;br /&gt;★&lt;code&gt;Parameter&lt;/code&gt; &lt;i&gt;t:A&lt;/i&gt;&lt;code&gt;.&lt;/code&gt;&lt;br /&gt;&lt;i&gt;t:A&lt;/i&gt;を environment に追加する。environmentはglobalなもの。&lt;br /&gt;&lt;br /&gt;★&lt;code&gt;Section&lt;/code&gt; &lt;i&gt;id&lt;/i&gt;&lt;code&gt;.&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;　    ...&lt;/pre&gt;&lt;br /&gt;　&lt;code&gt;End&lt;/code&gt; &lt;i&gt;id&lt;/i&gt;&lt;code&gt;.&lt;/code&gt;&lt;br /&gt;localなblockを作る。&lt;br /&gt;&lt;br /&gt;★&lt;code&gt;Variable&lt;/code&gt; &lt;i&gt;t:A&lt;/i&gt;&lt;code&gt;.&lt;/code&gt;&lt;br /&gt;&lt;i&gt;t:A&lt;/i&gt;を context に追加する。contextはlocal。なので、&lt;code&gt;Section...End&lt;/code&gt;の範囲内で有効。&lt;br /&gt;&lt;br /&gt;(2) Inference Rules&lt;br /&gt;&lt;br /&gt;様々な推論規則があります。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    (x,A)∈E∪Γ&lt;br /&gt;Var ------------    x:identifier&lt;br /&gt;    E,Γ |- x:A&lt;br /&gt;&lt;br /&gt; E,Γ|- e_1:A-&gt;B  E,Γ|- e_2:A&lt;br /&gt;App ------------------------------  関数適用&lt;br /&gt;    E,Γ|- e_1 e_2:B&lt;br /&gt; &lt;br /&gt;  E,Γ|- e:A_1 -&gt; A_2 -&gt; ... -&gt; A_n -&gt; B   E,Γ|- e_i:A_i (i=1,...,n) &lt;br /&gt;App* -------------------------------------------------------------------&lt;br /&gt;     E,Γ|- e e_1 ... e_n:B&lt;br /&gt; &lt;br /&gt; E,Γ|- t_1:A  E,Γ::(v:=t_1) |- t_2:B&lt;br /&gt;Lam --------------------------------------  λ式&lt;br /&gt;    E,Γ|- fun v:A =&gt; e:A-&gt;B&lt;br /&gt; &lt;br /&gt;    E,Γ|- t_1:A  E,Γ::(v:=t_1) |- t_2:B&lt;br /&gt;Let-in --------------------------------------  let&lt;br /&gt;       E,Γ|- let v:=t_1 in t_2:B&lt;br /&gt;    &lt;br /&gt;      E,Γ|- A:Set  E,Γ|- B:Set&lt;br /&gt;Prod-Set --------------------------&lt;br /&gt;         E,Γ|- A-&gt;B:Set&lt;br /&gt;&lt;br /&gt;  E,Γ|- t:A  E,Γ|- A ≦_{beta delta iota zeta} B&lt;br /&gt;Conv --------------------------&lt;br /&gt;     E,Γ|- t:B&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(3) Eval&lt;br /&gt;&lt;br /&gt;★cvb : call-by-value (cbvでなくlazyで遅延評価)&lt;br /&gt;&lt;br /&gt;★delta-reduction : t ==&gt; t{v/t'}。tのidentifier vをその定義t'で置換。&lt;br /&gt;&lt;br /&gt;★beta-reduction : (fun v:T =&gt; e_1) e2 ==&gt; e_1{v/e_2}。λ式を簡約。&lt;br /&gt;&lt;br /&gt;★zeta-reduction : let v := e_1 in e_2 ==&gt; e_2{v/e_1}。letを簡約。&lt;br /&gt;&lt;br /&gt;★iota-reduction : 帰納的な処理で詳しくはChap.6でということで後回し。nat,Zは帰納的な定義なので計算する時はiota-reductionが必須。&lt;br /&gt;&lt;br /&gt;★compute = cvb iota beta zeta delta の略&lt;br /&gt;&lt;br /&gt;★&lt;code&gt;Eval compute in (....).&lt;/code&gt; : &lt;code&gt;...&lt;/code&gt;を実際に計算する。&lt;br /&gt;&lt;br /&gt;Reductionに関する性質&lt;ul&gt;&lt;br /&gt;&lt;li&gt;strong normalization : reductionはfinite&lt;br /&gt;&lt;li&gt;confluence : t |&gt; t_1, t |&gt; t_2 ならば、あるt_3があって、t_1 |&gt; t_3 かつ t_2 |&gt; t_3。&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;(4) Universe&lt;br /&gt;&lt;br /&gt;typeもtermだとすると、typeのtypeがあるはず。それをsortという。&lt;br /&gt;CoqではSetというデフォルトのsortが定義されている。&lt;br /&gt;更にその上の無限の階層まで考えるようだが、CoqではType(i)は全部ひっくるめてTypeにしてしまう様子。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Level 0 : 具体的な項とか関数。O, S, trinomial,...&lt;br /&gt;Level 1 : データの型。nat, nat-&gt;nat, ...&lt;br /&gt;Level 2 : ソート。Set&lt;br /&gt;Level 3 : Type(0)&lt;br /&gt;   :&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3064288676757573633?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3064288676757573633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3064288676757573633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3064288676757573633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3064288676757573633'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/04/coq-coqart-chap2.html' title='[Coq] Coq&apos;Art Chap.2'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-1412661059076047076</id><published>2009-03-29T21:48:00.002+09:00</published><updated>2009-03-29T21:54:50.765+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq'Art Reading in Tokyo ?</title><content type='html'>ところで東京近辺でSpringerのCoq本&lt;a href="http://www.labri.fr/perso/casteran/CoqArt/index.html"&gt;Interactive Theorem Proving and Program Development. Coq'Art: The Calculus of Inductive Constructions&lt;/a&gt;に興味のある人っています？&lt;br /&gt;何人かいるようならば読書会でもとか思うのですが。なお、私は素人で型理論の専門家とかではありません。なので他人に教える程の知識は無く、一緒に勉強する感じになってしまいますが。&lt;br /&gt;逆に既に本を読んでいるとかで、私が参加しても構わないグループとかありましたら声をかけて下さい。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1412661059076047076?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/1412661059076047076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=1412661059076047076' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1412661059076047076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/1412661059076047076'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/03/coq-coqart-reading-in-tokyo.html' title='[Coq] Coq&apos;Art Reading in Tokyo ?'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-3404468389699569657</id><published>2009-03-29T21:08:00.004+09:00</published><updated>2009-03-29T21:47:34.472+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>[Coq] Coq'Art Chap.1</title><content type='html'>&lt;a href="http://www.labri.fr/perso/casteran/CoqArt/index.html"&gt;Interactive Theorem Proving and Program Development; Coq'Art: The Calculus of Inductive Constructions&lt;/a&gt;を読み始める事にしました。&lt;br /&gt;&lt;br /&gt;Chap.1ではinsertion sortを例にしてCoqの解説が行われています。そこで、Appendixのinsertion sortのコードをCoqIdeに入力してみました。実際に証明が自分で出来る様になるのは将来の課題として、とりあえずCoqでの開発の流れを追ってみます。&lt;br /&gt;なお証明自体は&lt;a href="http://www.labri.fr/perso/casteran/CoqArt/horizon/SRC/insertionv8.v"&gt;insertionv8.v&lt;/a&gt;にあります。&lt;br /&gt;&lt;br /&gt;まず、list Zがソートされた状態を定義する&lt;code&gt;sorted : list Z -&gt; Prop&lt;/code&gt;を定義します。こんな感じです。&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Inductive sorted : list Z -&gt; Prop :=&lt;br /&gt;  | sorted0 : sorted nil&lt;br /&gt;  | sorted1 : forall z:Z, sorted (z :: nil)&lt;br /&gt;  | sorted2 : forall (z1 z2:Z) (l:list Z), &lt;br /&gt;       z1 &lt;= z2 -&gt; sorted (z2 :: l) -&gt; sorted (z1 :: z2 :: l).&lt;br /&gt;&lt;/pre&gt;&lt;code&gt;sorted&lt;/code&gt;は定義なのでこれ自体は証明の対象ではありません。&lt;br /&gt;&lt;br /&gt;これを用いて、&lt;pre&gt;&lt;br /&gt;Theorem sorted_inv : &lt;br /&gt;  forall (z:Z) (l:list Z), sorted (z :: l) -&gt; sorted l.&lt;br /&gt;&lt;/pre&gt;を証明します。&lt;br /&gt;&lt;br /&gt;次いで、並べ替えであることを示す&lt;code&gt;equiv&lt;/code&gt;を定義します。まず、リストのなかの出現数を示す&lt;pre&gt;&lt;br /&gt;Fixpoint nb_occ (z:Z) (l:list Z) {struct l} : nat :=&lt;br /&gt;  match l with&lt;br /&gt;  | nil =&gt; 0%nat&lt;br /&gt;  | (z' :: l') =&gt;&lt;br /&gt;      match Z_eq_dec z z' with&lt;br /&gt;      | left _ =&gt; S (nb_occ z l')&lt;br /&gt;      | right _ =&gt; nb_occ z l'&lt;br /&gt;      end&lt;br /&gt;  end.&lt;br /&gt;&lt;/pre&gt;を定義します。この&lt;code&gt;nb_occ&lt;/code&gt;は定義なので証明しません。&lt;br /&gt;&lt;br /&gt;これを使って、&lt;pre&gt;&lt;br /&gt;Definition equiv (l l':list Z) := forall z:Z, nb_occ z l = nb_occ z l'&lt;br /&gt;&lt;/pre&gt;を定義します。これ自体も証明しません。&lt;br /&gt;&lt;br /&gt;&lt;code&gt;nb_occ, equiv&lt;/code&gt;の定義から、下記の補題を証明します。&lt;pre&gt;&lt;br /&gt;Lemma equiv_refl : &lt;br /&gt;  forall l:list Z, equiv l l.&lt;br /&gt;Lemma equiv_sym : &lt;br /&gt;  forall l l':list Z, equiv l l' -&gt; equiv l' l.&lt;br /&gt;Lemma equiv_trans : &lt;br /&gt;  forall l l' l'':list Z, equiv l l' -&gt; equiv l' l'' -&gt; equiv l l''.&lt;br /&gt;Lemma equiv_cons : &lt;br /&gt;  forall (z:Z) (l l':list Z), equiv l l' -&gt; equiv (z :: l) (z :: l').&lt;br /&gt;Lemma equiv_perm : &lt;br /&gt;  forall (a b:Z) (l l':list Z), equiv l l' -&gt; equiv (a :: b :: l) (b :: a :: l').&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;次いで、実際にinsertion sortを行う関数&lt;code&gt;aux : Z -&gt; list Z -&gt; list Z&lt;/code&gt;を定義します。&lt;pre&gt;&lt;br /&gt;Fixpoint aux (z:Z) (l:list Z) {struct l} : list Z :=&lt;br /&gt;  match l with&lt;br /&gt;  | nil =&gt; z :: nil&lt;br /&gt;  | cons a l' =&gt;&lt;br /&gt;      match Z_le_gt_dec z a with&lt;br /&gt;      | left _ =&gt;  z :: a :: l'&lt;br /&gt;      | right _ =&gt; a :: (aux z l')&lt;br /&gt;      end&lt;br /&gt;  end.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;aux&lt;/code&gt;がinsertion sortの性質を持っている事を示す補題、つまりauxの結果がequivであること、sortedであることを証明します。&lt;pre&gt;&lt;br /&gt;Lemma aux_equiv : &lt;br /&gt;  forall (l:list Z) (x:Z), equiv (x :: l) (aux x l).&lt;br /&gt;Lemma aux_sorted : &lt;br /&gt;  forall (l:list Z) (x:Z), sorted l -&gt; sorted (aux x l).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;最後に、&lt;code&gt;sort:list Z -&gt; list Z&lt;/code&gt;を定義というか、sortされた出力の存在を証明します。&lt;pre&gt;&lt;br /&gt;Definition sort :　forall l:list Z, {l' : list Z | equiv l l' /\ sorted l'}.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;証明を追いきれてないのですが、どうも&lt;code&gt;exists (aux a l')&lt;/code&gt;の様に、実例を示して存在を証明するみたいに&lt;code&gt;aux&lt;/code&gt;を使っているようです。&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sorted, nb_occ, equiv&lt;/code&gt;は定義なので証明の対象ではありません。&lt;br /&gt;&lt;code&gt;aux, sort&lt;/code&gt;は成果物として得る、証明済みのプログラムです。&lt;code&gt;sort&lt;/code&gt;を満たす具体的な&lt;code&gt;l'&lt;/code&gt;の値として&lt;code&gt;aux&lt;/code&gt;を使った式を与えます。その値が&lt;code&gt;l'&lt;/code&gt;の条件を満たす事は&lt;code&gt;aux_equiv, aux_sorted&lt;/code&gt;から保証されます。&lt;br /&gt;&lt;br /&gt;一般的に&lt;ul&gt;&lt;br /&gt;&lt;li&gt;仕様を表す様な述語(X -&gt; Prop)を書く。仕様に関する補題も証明しておく。&lt;br /&gt;&lt;li&gt;解を与える様な関数を書く。&lt;br /&gt;&lt;li&gt;その関数の出力が仕様を満たす事を証明する。&lt;br /&gt;&lt;/ul&gt;とかすれば良い様に見えます。&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;ある程度、この本を読み終わった後で、またこのプログラムを振り返ってみたいと思います。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3404468389699569657?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/3404468389699569657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=3404468389699569657' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3404468389699569657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/3404468389699569657'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2009/03/coq-coqart-chap1.html' title='[Coq] Coq&apos;Art Chap.1'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-8406036019476006883</id><published>2008-12-27T15:34:00.004+09:00</published><updated>2008-12-27T16:13:39.542+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RWH'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>[Haskell][RWH] Chapter 1</title><content type='html'>RWHのChapter 1を読む。&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;not equalは&lt;code&gt;!=&lt;/code&gt;ではなく&lt;code&gt;/=&lt;/code&gt;。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;temporary definitionを&lt;code&gt;let&lt;/code&gt;で。例えば、&lt;code&gt;ghci&gt; &lt;b&gt;let e = exp 1&lt;/b&gt;&lt;/code&gt;とか。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;ghci&gt; &lt;b&gt;:info []&lt;/b&gt;&lt;/code&gt;とかすれば、[]の情報が調べられる。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;ghci&gt; &lt;b&gt;:set +t&lt;/b&gt;&lt;/code&gt;で型情報を表示する。解除は&lt;code&gt;&lt;b&gt;:unset +t&lt;/b&gt;&lt;/code&gt;。&lt;code&gt;&lt;b&gt;:type it&lt;/b&gt;&lt;/code&gt;でunsetしても簡単に調べられる。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;it&lt;/code&gt;で前の計算結果を参照出来る。&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;簡単にHaskellのプログラムを書くにはinteractを使えば良いらしい。&lt;br /&gt;main = interact f 但し、fはString -&gt; Stringな関数。これで標準入力から読んで標準出力に書けば良い。&lt;br /&gt;&lt;code&gt;&lt;br /&gt;% cat WC.hs&lt;br /&gt;main = interact wordCount&lt;br /&gt;    where wordCount input = show (length (lines input)) + "\n"&lt;br /&gt;%&lt;br /&gt;&lt;br /&gt;Prelude&gt; :info interact&lt;br /&gt;interact :: (String -&gt; String) -&gt; IO ()  -- Defined in System.IO&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;実行は&lt;br /&gt;&lt;code&gt;% runghc WC.hs &lt; quux.txt&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Exerciseはとりあえずこんな感じ？&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;main = interact wordCount&lt;br /&gt;    where wordCount input = numLines input ++ "\t" ++ numWords input ++ "\t" ++ numChars input ++ "\n"&lt;br /&gt;          numLines input = show (length (lines input))&lt;br /&gt;          numWords input = show (length (words input))&lt;br /&gt;          numChars input = show (length input)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8406036019476006883?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/8406036019476006883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=8406036019476006883' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8406036019476006883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/8406036019476006883'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2008/12/haskellrwh-chapter-1.html' title='[Haskell][RWH] Chapter 1'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30049755.post-2522921553923845427</id><published>2008-12-04T23:07:00.003+09:00</published><updated>2008-12-04T23:13:36.505+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>[Scala] map and flatMap on scala.Function1</title><content type='html'>&lt;a href="http://blog.tmorris.net/scalafunction1-lacking/"&gt;scala.Function1 lacking&lt;/a&gt; @ λ Tony’s blog λ&lt;br /&gt;&lt;br /&gt;Scalaの関数の型の scala.Function1 にもっと便利な機能を、という話。&lt;br /&gt;mapはともかくflatMapをこうやって定義するのか、というのはなんか勉強になったので、メモ代わりに。&lt;br /&gt;同様に S combinator というのも自分ではなんか巧く使えないものなので参考になるなぁ、と。on は普通に便利かも。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2522921553923845427?l=study-func-prog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://study-func-prog.blogspot.com/feeds/2522921553923845427/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30049755&amp;postID=2522921553923845427' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2522921553923845427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30049755/posts/default/2522921553923845427'/><link rel='alternate' type='text/html' href='http://study-func-prog.blogspot.com/2008/12/scala-map-and-flatmap-on-scalafunction1.html' title='[Scala] map and flatMap on scala.Function1'/><author><name>Takashi Miyamoto</name><uri>http://www.blogger.com/profile/15445314693808242249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
