<?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-3963822990972949627</id><updated>2012-02-16T21:57:42.193+09:00</updated><title type='text'>Utotch Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://utotch.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963822990972949627/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://utotch.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>utotch</name><uri>http://www.blogger.com/profile/13699023887797793677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-ATEw_Fx2qWY/TrLC2aSrbuI/AAAAAAACx40/U-3dfXKELdk/s220/kuto_face.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>3</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3963822990972949627.post-5590962929389877730</id><published>2011-12-19T00:43:00.001+09:00</published><updated>2011-12-19T00:43:57.052+09:00</updated><title type='text'>Pandoc で Blogger の記事を書く</title><content type='html'>&lt;h3 id="pandoc-で-様々なフォーマットの文書を作成する"&gt;Pandoc で 様々なフォーマットの文書を作成する&lt;/h3&gt;&lt;a href="http://tanakh.jp/posts/2011-11-05-haskell-infra.html"&gt;tanakhさんの記事&lt;/a&gt;で、&lt;a href="http://johnmacfarlane.net/pandoc/"&gt;Pandoc&lt;/a&gt; という Haskell 製の文書フォーマット変換ツールがあることを知りました。私は、Emacs + SKK で文書を書くのが最もストレスが低いので、Emacsで文書を書いて、他のフォーマットに変換できると非常に幸せです。とりあえず、Blogger の Blog 記事を書くときの Pandoc の活用方法についてメモしておきます。&lt;br /&gt;&lt;h3 id="インストール"&gt;インストール&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; cabal install pandoc -fhighlighting&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;-fhighlighting でシンタックスハイライト機能を有効にしておきます。&lt;br /&gt;&lt;h3 id="使いかた"&gt;使いかた&lt;/h3&gt;&lt;a href="http://johnmacfarlane.net/pandoc/"&gt;Pandoc のページ&lt;/a&gt; を見ると、Markdown, reStructuredText 等の様々なフォーマットから HTML, PDF, ... 等の多様なフォーマットに変換できることが書いてあります。&lt;br /&gt;とりあえず、"Markdown 形式で文書を書いて、HTMLに変換し、Blogger の記事にする" という目的で使います。&lt;br /&gt;この記事も勿論, Markdown で書いています。&lt;br /&gt;&lt;h3 id="変換のしかた"&gt;変換のしかた&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; pandoc markdown_file.txt -o output.html&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;で Markdown -&amp;gt; HTML に変換できます。&lt;br /&gt;&lt;h3 id="markdown-の文法"&gt;Markdown の文法&lt;/h3&gt;&lt;a href="http://daringfireball.net/projects/markdown/syntax"&gt;ココ(DALING FIREBALL)&lt;/a&gt;や, &lt;a href="http://ja.wikipedia.org/wiki/Markdown"&gt;ココ(Wikipedia)&lt;/a&gt; が参考になるでしょう。&lt;br /&gt;&lt;h3 id="haskell-のソースを-syntax-highlighting-する"&gt;Haskell のソースを Syntax Highlighting する&lt;/h3&gt;Haskell のソースを Syntax Hilighting する方法を書きます。(そもそもコレをメモしたかったので、この記事を書きました)&lt;br /&gt;通常、Markdown で program source を書くには、先頭に4文字以上の空白を入れてインデントすればいいみたいですが、これでは Syntax Highlight してくれないようです。また、私は空白でインデントする書き方が好きではありません。&lt;br /&gt;&lt;a href="http://johnmacfarlane.net/pandoc/README.html"&gt;ココ&lt;/a&gt;に情報がありますが、ソースコード等を書くには&lt;br /&gt;&lt;pre&gt;&lt;code&gt;~~~~~~&lt;br /&gt;source code here&lt;br /&gt;~~~~~~&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;のように、tilde 6 個以上で囲んで、その間に書けばいいみたいです。&lt;br /&gt;Haskell のコードを Syntax Highlight するには、&lt;br /&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;~~~~~~&lt;/span&gt;{&lt;span class="fu"&gt;.&lt;/span&gt;haskell}&lt;br /&gt;&lt;span class="ot"&gt;hoge&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;[&lt;span class="dt"&gt;Char&lt;/span&gt;]&lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="dt"&gt;Int&lt;/span&gt;&lt;br /&gt;hoge (x&lt;span class="fu"&gt;:&lt;/span&gt;xs) &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;undefined&lt;/span&gt;&lt;br /&gt;&lt;span class="fu"&gt;~~~~~~&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;のように、上の行を &lt;code&gt;~~~~~~{.haskell}&lt;/code&gt; にすればいいみたいです。 行番号を入れるには、&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;~~~~~~&lt;/span&gt;{&lt;span class="fu"&gt;.&lt;/span&gt;haskell &lt;span class="fu"&gt;.&lt;/span&gt;numberLines}&lt;br /&gt;&lt;span class="ot"&gt;hoge&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;[&lt;span class="dt"&gt;Char&lt;/span&gt;]&lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="dt"&gt;Int&lt;/span&gt;&lt;br /&gt;hoge (x&lt;span class="fu"&gt;:&lt;/span&gt;xs) &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;undefined&lt;/span&gt;&lt;br /&gt;&lt;span class="fu"&gt;~~~~~~&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;のように、上の行を &lt;code&gt;~~~~~~{.haskell .numberLines}&lt;/code&gt; にすればいいみたいです。&lt;br /&gt;これを html に変換して Blogger の記事に貼ればよいのですが、色の部分は css で実現されているため、css を変更しないと色が付きません。&lt;br /&gt;Blogger のテンプレートの カスタム css の部分に、以下の css を追加します。 (&lt;code&gt;pandoc -s file.txt -o html&lt;/code&gt; で出力した HTML の &lt;br /&gt;の部分から抽出したものです)&lt;br /&gt;&lt;pre&gt;&lt;code&gt;table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre &lt;br /&gt;   { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; }&lt;br /&gt;td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }&lt;br /&gt;td.sourceCode { padding-left: 5px; }&lt;br /&gt;code.sourceCode span.kw { color: #007020; font-weight: bold; } &lt;br /&gt;code.sourceCode span.dt { color: #902000; }&lt;br /&gt;code.sourceCode span.dv { color: #40a070; }&lt;br /&gt;code.sourceCode span.bn { color: #40a070; }&lt;br /&gt;code.sourceCode span.fl { color: #40a070; }&lt;br /&gt;code.sourceCode span.ch { color: #4070a0; }&lt;br /&gt;code.sourceCode span.st { color: #4070a0; }&lt;br /&gt;code.sourceCode span.co { color: #60a0b0; font-style: italic; }&lt;br /&gt;code.sourceCode span.ot { color: #007020; }&lt;br /&gt;code.sourceCode span.al { color: red; font-weight: bold; }&lt;br /&gt;code.sourceCode span.fu { color: #06287e; }&lt;br /&gt;code.sourceCode span.re { }&lt;br /&gt;code.sourceCode span.er { color: red; font-weight: bold; }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;これで、上記の Markdown を変換した HTML を記事に貼れば、シンタックスハイライトされます。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3963822990972949627-5590962929389877730?l=utotch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://utotch.blogspot.com/feeds/5590962929389877730/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://utotch.blogspot.com/2011/12/pandoc-blogger.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963822990972949627/posts/default/5590962929389877730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963822990972949627/posts/default/5590962929389877730'/><link rel='alternate' type='text/html' href='http://utotch.blogspot.com/2011/12/pandoc-blogger.html' title='Pandoc で Blogger の記事を書く'/><author><name>utotch</name><uri>http://www.blogger.com/profile/13699023887797793677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-ATEw_Fx2qWY/TrLC2aSrbuI/AAAAAAACx40/U-3dfXKELdk/s220/kuto_face.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963822990972949627.post-7521319094250694483</id><published>2011-12-18T15:20:00.001+09:00</published><updated>2011-12-19T11:48:19.900+09:00</updated><title type='text'>Haskell で parser を書くには (初心者編)</title><content type='html'>Haskell で parser を書くには (初心者編)&lt;br /&gt;&lt;h4 id="勝手に-haskell-advent-calendar-2011"&gt;勝手に Haskell Advent Calendar 2011&lt;/h4&gt;&lt;a href="http://partake.in/events/eaea52c2-61ef-46d5-a855-3a2dde459e3a"&gt;Haskell Advent Calendar 2011&lt;/a&gt; にはエントリーできませんでしたけど、一人寂しく「勝手に Haskell Advent Calendar 2011」を開催して、わくわくクリスマスを待ちたいと思います。&lt;br /&gt;&lt;h4 id="目的"&gt;目的:&lt;/h4&gt;Parsec3 と attoparsec の基本的使用法, Applicative スタイルを習得する&lt;br /&gt;&lt;h4 id="前置き"&gt;前置き:&lt;/h4&gt;Haskell で parser を書くにはどうすればいいのでしょうか? 私は、これを勉強すべく情報源を探しましたが、一体どこからどう始めればいいのか分からず、非常に混乱しました。「この記事を読めば大体概要が全部分かる」という情報源が日本語でも英語でも見つけられなかったからです。なので自分でまとめてみることにしました。 (私は、まだ Haskell 初心者+αのレベルで、parser の情報も現時点での情報ということをご理解ください)&lt;br /&gt;私が混乱したのは、以下のような情報に出会ったからです。&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Programming In Haskell に書いてある parser は、本の中のコードのみでは動かない&lt;/li&gt;&lt;li&gt;Haskell で parser を書くには、Parsec を使うとよいらしい&lt;/li&gt;&lt;li&gt;Parsec2 は使うな。Parsec3 使え。&lt;/li&gt;&lt;li&gt;Real World Haskell は Parsec2 で記述されているので古い&lt;/li&gt;&lt;li&gt;Parsec は遅い。attoparsec は速い。&lt;/li&gt;&lt;li&gt;attoparsec は、エラーメッセージが不親切&lt;/li&gt;&lt;/ul&gt;？？？。一体どうすればいいのでしょうか? Parsec はいいの?ダメなの? attoparsec はいいの?ダメなの? 最良の選択肢は、どれなの??&lt;br /&gt;勉強会で質問してみた結果、以下のように理解しました。&lt;br /&gt;&lt;ul&gt;&lt;li&gt;デファクトスタンダードが どれか一つ というわけではなく、皆さんは "Parsec3" と "attoparsec" を使い分けているようだ&lt;/li&gt;&lt;li&gt;Parsec3 は attoparsec より速度は遅いが、エラーメッセージが親切&lt;/li&gt;&lt;li&gt;attoparsec は Parsec3 より速度は速いが、エラーメッセージが不親切&lt;/li&gt;&lt;li&gt;ニーズに応じて Parsec3 と attoparsec を使い分ける(もしくは両方使う)のがオススメ。でも、Parsec2 は古いので使わないことをオススメ&lt;/li&gt;&lt;/ul&gt;やっと状況が分かりました。Parsec3 と attoparsec を理解すればいいようです。しかし、それでも まだ困惑は残りました。なぜなら、Parsec3 と attoparsec の初心者向けの、よい Tutorial 記事を見つけられなかったからです。&lt;br /&gt;この記事では、「Parsec3 と attoparsec の基本的な書きかたを理解する」ことを目的とします。副産物として、Applicative スタイルというのに触れます。&lt;br /&gt;順番としては、以下の順番で書きます。&lt;br /&gt;&lt;ul&gt;&lt;li&gt;(1): 簡単な BNF を定義する&lt;/li&gt;&lt;li&gt;(2): Parsec3 で、(1) を解析してみる&lt;/li&gt;&lt;li&gt;(3): (2) を Applicative スタイルにする&lt;/li&gt;&lt;li&gt;(4): (3) を attoparsec に移植する&lt;/li&gt;&lt;li&gt;(5): さらに勉強するための情報源&lt;/li&gt;&lt;/ul&gt;尚, 内容のほとんどは、&lt;a href="http://d.hatena.ne.jp/kazu-yamamoto/20101211/1292021817"&gt;kazu-yamamoto さんの記事&lt;/a&gt; を参考にさせていただいてます。(kazu さん ありがとうございます)&lt;br /&gt;&lt;h3 id="簡単な-bnf-を定義する"&gt;(1): 簡単な BNF を定義する&lt;/h3&gt;&lt;a href="http://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0Haskell-Graham-Hutton/dp/4274067815"&gt;プログラミング Haskell&lt;/a&gt; の 8章の内容を多少簡単化して、 "1ケタの数字の加算と乗算ができるパーサー" を題材にします。BNF は以下です。&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;expr &lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="fu"&gt;=&lt;/span&gt; term &lt;span class="ch"&gt;'+'&lt;/span&gt; expr &lt;span class="fu"&gt;|&lt;/span&gt; term&lt;br /&gt;term &lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="fu"&gt;=&lt;/span&gt; factor &lt;span class="ch"&gt;'*'&lt;/span&gt; term &lt;span class="fu"&gt;|&lt;/span&gt; factor&lt;br /&gt;factor &lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="ch"&gt;'('&lt;/span&gt; expr &lt;span class="ch"&gt;')'&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; nat&lt;br /&gt;nat &lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="ch"&gt;'0'&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; &lt;span class="ch"&gt;'1'&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; &lt;span class="ch"&gt;'2'&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;1ケタの数値のみしか扱えませんが、()が使え、乗算が加算より優先順位が高く、'+','*'は右結合になっています。&lt;br /&gt;&lt;h3 id="parsec3-で1-を解析してみる"&gt;(2): Parsec3 で、(1) を解析してみる&lt;/h3&gt;上記 (1) のBNF を解析し、data Exp 型の結果を返す parser を Parsec3 で実装します。Parsec3 を使うには&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Text.Parsec&lt;/span&gt;&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Text.Parsec.String&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;します。 次に、BNF の定義を Haskell のコードに対応させて実装していきます。BNF で、選択を意味する '|' は、Haskellでは、Text.Parsec.(&amp;lt;|&amp;gt;) という二項演算子です。 (本:プログラミングHaskell では、(+++) と記述されています) 一文字の記号 '+', '*' を parse するには&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;char c&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;を使います。文字が、複数の文字リスト(ex:数字列)のどれかにマッチすればよい場合は、&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;oneOf [&lt;span class="dt"&gt;Char&lt;/span&gt;]&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;を使います。 &lt;a href="https://github.com/utotch/StudyHaskell/blob/master/Parsec3Sample1.hs"&gt;ParsecSample1.hs&lt;/a&gt;&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;8&lt;br /&gt;9&lt;br /&gt;10&lt;br /&gt;11&lt;br /&gt;12&lt;br /&gt;13&lt;br /&gt;14&lt;br /&gt;15&lt;br /&gt;16&lt;br /&gt;17&lt;br /&gt;18&lt;br /&gt;19&lt;br /&gt;20&lt;br /&gt;21&lt;br /&gt;22&lt;br /&gt;23&lt;br /&gt;24&lt;br /&gt;25&lt;br /&gt;26&lt;br /&gt;27&lt;br /&gt;28&lt;br /&gt;29&lt;br /&gt;30&lt;br /&gt;31&lt;br /&gt;32&lt;br /&gt;33&lt;br /&gt;34&lt;br /&gt;35&lt;br /&gt;36&lt;br /&gt;37&lt;br /&gt;38&lt;br /&gt;39&lt;br /&gt;40&lt;br /&gt;41&lt;br /&gt;42&lt;br /&gt;43&lt;br /&gt;44&lt;br /&gt;45&lt;br /&gt;46&lt;br /&gt;47&lt;br /&gt;48&lt;br /&gt;49&lt;br /&gt;50&lt;br /&gt;51&lt;br /&gt;52&lt;br /&gt;53&lt;br /&gt;54&lt;br /&gt;55&lt;br /&gt;56&lt;br /&gt;57&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Char&lt;/span&gt; (&lt;span class="fu"&gt;ord&lt;/span&gt;)&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Text.Parsec&lt;/span&gt; (char, oneOf, (&lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;), parseTest)&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Text.Parsec.String&lt;/span&gt; (&lt;span class="dt"&gt;Parser&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Add&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Mul&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Nat&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="kw"&gt;deriving&lt;/span&gt; &lt;span class="kw"&gt;Show&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;{- BNF of one digit addtion &amp;amp; multiplication&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;expr ::= term ('+' expr | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;term ::= factor ('*' term | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;factor ::= '(' expr ')' | nat&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;nat ::= '0' | '1' | '2' | ...&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;-}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- expr ::= term ('+' expr | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;expr&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;&lt;br /&gt;expr &lt;span class="fu"&gt;=&lt;/span&gt; &lt;br /&gt;  &lt;span class="kw"&gt;do&lt;/span&gt; &lt;br /&gt;    t &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; term&lt;br /&gt;    &lt;span class="kw"&gt;do&lt;/span&gt;&lt;br /&gt;      char &lt;span class="ch"&gt;'+'&lt;/span&gt;&lt;br /&gt;      e &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; expr&lt;br /&gt;      &lt;span class="fu"&gt;return&lt;/span&gt; (&lt;span class="dt"&gt;Add&lt;/span&gt; t e)&lt;br /&gt;     &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;return&lt;/span&gt; t&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- term ::= factor ('*' term | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;term&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;&lt;br /&gt;term &lt;span class="fu"&gt;=&lt;/span&gt; &lt;br /&gt;  &lt;span class="kw"&gt;do&lt;/span&gt;&lt;br /&gt;    f &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; factor&lt;br /&gt;    &lt;span class="kw"&gt;do&lt;/span&gt;&lt;br /&gt;      char &lt;span class="ch"&gt;'*'&lt;/span&gt;&lt;br /&gt;      t &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; term&lt;br /&gt;      &lt;span class="fu"&gt;return&lt;/span&gt; (&lt;span class="dt"&gt;Mul&lt;/span&gt; f t)&lt;br /&gt;     &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;return&lt;/span&gt; f&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- factor ::= '(' expr ')' | nat&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;factor&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;    &lt;br /&gt;factor &lt;span class="fu"&gt;=&lt;/span&gt; &lt;br /&gt;  &lt;span class="kw"&gt;do&lt;/span&gt;&lt;br /&gt;    char &lt;span class="ch"&gt;'('&lt;/span&gt;&lt;br /&gt;    e &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; expr&lt;br /&gt;    char &lt;span class="ch"&gt;')'&lt;/span&gt;&lt;br /&gt;    &lt;span class="fu"&gt;return&lt;/span&gt; e&lt;br /&gt;   &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; nat&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- nat ::= '0' | '1' | '2' | ...&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;nat&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;&lt;br /&gt;nat &lt;span class="fu"&gt;=&lt;/span&gt; &lt;br /&gt;  &lt;span class="kw"&gt;do&lt;/span&gt;&lt;br /&gt;    c &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; oneOf [&lt;span class="ch"&gt;'0'&lt;/span&gt;&lt;span class="fu"&gt;..&lt;/span&gt;&lt;span class="ch"&gt;'9'&lt;/span&gt;]&lt;br /&gt;    &lt;span class="fu"&gt;return&lt;/span&gt; (&lt;span class="dt"&gt;Nat&lt;/span&gt; (charToInt c))&lt;br /&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;br /&gt;    charToInt c &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;ord&lt;/span&gt; c &lt;span class="fu"&gt;-&lt;/span&gt; &lt;span class="fu"&gt;ord&lt;/span&gt; &lt;span class="ch"&gt;'0'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;{- How to test this&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;parseTest expr "1+2*3"&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;parseTest expr "(1+2)*3"&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;-}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;do の後に、素直に BNF の個々の定義を並べて処理して行けばよいのですが、ちょっと読みにくいですね(このままだと、「BNFをそのまま実装できる」は、ちょっと言い過ぎな感じ)。 動作をテストするには、ghci にロードして&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;parseTest expr &lt;span class="st"&gt;"1+2*3"&lt;/span&gt;&lt;br /&gt;parseTest expr &lt;span class="st"&gt;"(1+2)*3"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;等で解析結果を確認できます。&lt;br /&gt;&lt;h3 id="を-applicative-スタイルにする"&gt;(3): (2) を Applicative スタイルにする&lt;/h3&gt;&lt;a href="http://d.hatena.ne.jp/kazu-yamamoto/20101211/1292021817"&gt;Applicative スタイル&lt;/a&gt; にすると、もっと簡潔に記述できます。やってみましょう。&lt;br /&gt;&lt;a href="https://github.com/utotch/StudyHaskell/blob/master/Parsec3Sample2.hs"&gt;ParsecSample2.hs&lt;/a&gt;&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;8&lt;br /&gt;9&lt;br /&gt;10&lt;br /&gt;11&lt;br /&gt;12&lt;br /&gt;13&lt;br /&gt;14&lt;br /&gt;15&lt;br /&gt;16&lt;br /&gt;17&lt;br /&gt;18&lt;br /&gt;19&lt;br /&gt;20&lt;br /&gt;21&lt;br /&gt;22&lt;br /&gt;23&lt;br /&gt;24&lt;br /&gt;25&lt;br /&gt;26&lt;br /&gt;27&lt;br /&gt;28&lt;br /&gt;29&lt;br /&gt;30&lt;br /&gt;31&lt;br /&gt;32&lt;br /&gt;33&lt;br /&gt;34&lt;br /&gt;35&lt;br /&gt;36&lt;br /&gt;37&lt;br /&gt;38&lt;br /&gt;39&lt;br /&gt;40&lt;br /&gt;41&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Applicative&lt;/span&gt; ((&lt;span class="fu"&gt;&amp;lt;$&amp;gt;&lt;/span&gt;),(&lt;span class="fu"&gt;*&amp;gt;&lt;/span&gt;),(&lt;span class="fu"&gt;&amp;lt;*&lt;/span&gt;),pure)&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Char&lt;/span&gt; (&lt;span class="fu"&gt;ord&lt;/span&gt;)&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Text.Parsec&lt;/span&gt; (char, oneOf, (&lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;), parseTest)&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Text.Parsec.String&lt;/span&gt; (&lt;span class="dt"&gt;Parser&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Add&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Mul&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Nat&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="kw"&gt;deriving&lt;/span&gt; &lt;span class="kw"&gt;Show&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;{- BNF of one digit addtion &amp;amp; multiplication&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;expr ::= term ('+' expr | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;term ::= factor ('*' term | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;factor ::= '(' expr ')' | nat&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;nat ::= '0' | '1' | '2' | ...&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;-}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- expr ::= term ('+' expr | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;expr&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;&lt;br /&gt;expr &lt;span class="fu"&gt;=&lt;/span&gt; &lt;br /&gt;  &lt;span class="kw"&gt;do&lt;/span&gt; &lt;br /&gt;    t &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; term&lt;br /&gt;    (&lt;span class="dt"&gt;Add&lt;/span&gt; t &lt;span class="fu"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; (char &lt;span class="ch"&gt;'+'&lt;/span&gt; &lt;span class="fu"&gt;*&amp;gt;&lt;/span&gt; expr)) &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; pure t&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- term ::= factor ('*' term | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;term&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;&lt;br /&gt;term &lt;span class="fu"&gt;=&lt;/span&gt; &lt;br /&gt;  &lt;span class="kw"&gt;do&lt;/span&gt;&lt;br /&gt;    f &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; factor&lt;br /&gt;    (&lt;span class="dt"&gt;Mul&lt;/span&gt; f &lt;span class="fu"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; (char &lt;span class="ch"&gt;'*'&lt;/span&gt; &lt;span class="fu"&gt;*&amp;gt;&lt;/span&gt; term)) &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; pure f    &lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- factor ::= '(' expr ')' | nat&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;factor&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;    &lt;br /&gt;factor &lt;span class="fu"&gt;=&lt;/span&gt; (char &lt;span class="ch"&gt;'('&lt;/span&gt; &lt;span class="fu"&gt;*&amp;gt;&lt;/span&gt; expr &lt;span class="fu"&gt;&amp;lt;*&lt;/span&gt; char &lt;span class="ch"&gt;')'&lt;/span&gt;) &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; nat&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- nat ::= '0' | '1' | '2' | ...&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;nat&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;&lt;br /&gt;nat &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Nat&lt;/span&gt; &lt;span class="fu"&gt;.&lt;/span&gt; charToInt &lt;span class="fu"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; oneOf [&lt;span class="ch"&gt;'0'&lt;/span&gt;&lt;span class="fu"&gt;..&lt;/span&gt;&lt;span class="ch"&gt;'9'&lt;/span&gt;]&lt;br /&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;br /&gt;    charToInt c &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;ord&lt;/span&gt; c &lt;span class="fu"&gt;-&lt;/span&gt; &lt;span class="fu"&gt;ord&lt;/span&gt; &lt;span class="ch"&gt;'0'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;{- How to test this&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;parseTest expr "1+2*3"&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;parseTest expr "(1+2)*3"&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;-}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;ぐっと短くなりましたね。これなら BNF を、そのまま Haskell コードに実装できると言っても過言ではなさそうです。 Applicative スタイルの詳細は、kazu さんの記事を参照していただくとよいですが、&lt;br /&gt;&lt;ul&gt;&lt;li&gt;pure は return と同じ (値を返り値の型に wrap する)&lt;/li&gt;&lt;li&gt;(&amp;lt;$&amp;gt;) は fmap (文脈に持ち上げる)&lt;/li&gt;&lt;li&gt;(*&amp;gt;) は左の処理結果を捨てて連結&lt;/li&gt;&lt;li&gt;(&amp;lt;*) は右の処理結果を捨てて連結&lt;/li&gt;&lt;/ul&gt;という意味のようです(私も勉強中...。)&lt;br /&gt;&lt;h3 id="を-attoparsec-に移植する"&gt;(4): (3) を attoparsec に移植する&lt;/h3&gt;なんとか Parsec3 を使って簡単な BNF を Haskell で解析できるようになりました。でも、&lt;a href="http://hackage.haskell.org/package/attoparsec-0.10.0.3"&gt;attoparsec&lt;/a&gt; も使ってみたいです。やってみましょう。&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;cabal install attoparsec&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;等で適当にインストールしてください(省略)。 attoparsec を使うには、先程の Parsec3 の import の変わりに、以下を記述します。&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Attoparsec.Text&lt;/span&gt;&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Text&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;attoparsec は String ではなくて、ByteString と Text を parse するようです。ここでは、Data.Text を使います。&lt;br /&gt;もしかして、import を変えれば、そのまま動いたりして、、と思ったのですが、Parsec3 にあった &lt;code&gt;oneOf&lt;/code&gt; という関数が無いようです。attoparsec の satisfy 関数を使ってテキトーに作ります。&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="ot"&gt;oneOf&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;[&lt;span class="dt"&gt;Char&lt;/span&gt;]&lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Char&lt;/span&gt; &lt;span class="co"&gt;-- attoparsec には oneOf がないので自作&lt;/span&gt;&lt;br /&gt;oneOf xs &lt;span class="fu"&gt;=&lt;/span&gt; satisfy &lt;span class="fu"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;flip&lt;/span&gt; &lt;span class="fu"&gt;elem&lt;/span&gt; &lt;span class="fu"&gt;$&lt;/span&gt; xs&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;ここだけ変更すれば、そのまま行けそうです。&lt;br /&gt;&lt;a href="https://github.com/utotch/StudyHaskell/blob/master/AttoparsecSample1.hs"&gt;AttoparsecSample1.hs&lt;/a&gt;&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;8&lt;br /&gt;9&lt;br /&gt;10&lt;br /&gt;11&lt;br /&gt;12&lt;br /&gt;13&lt;br /&gt;14&lt;br /&gt;15&lt;br /&gt;16&lt;br /&gt;17&lt;br /&gt;18&lt;br /&gt;19&lt;br /&gt;20&lt;br /&gt;21&lt;br /&gt;22&lt;br /&gt;23&lt;br /&gt;24&lt;br /&gt;25&lt;br /&gt;26&lt;br /&gt;27&lt;br /&gt;28&lt;br /&gt;29&lt;br /&gt;30&lt;br /&gt;31&lt;br /&gt;32&lt;br /&gt;33&lt;br /&gt;34&lt;br /&gt;35&lt;br /&gt;36&lt;br /&gt;37&lt;br /&gt;38&lt;br /&gt;39&lt;br /&gt;40&lt;br /&gt;41&lt;br /&gt;42&lt;br /&gt;43&lt;br /&gt;44&lt;br /&gt;45&lt;br /&gt;46&lt;br /&gt;47&lt;br /&gt;48&lt;br /&gt;49&lt;br /&gt;50&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Applicative&lt;/span&gt; ((&lt;span class="fu"&gt;&amp;lt;$&amp;gt;&lt;/span&gt;),(&lt;span class="fu"&gt;*&amp;gt;&lt;/span&gt;),(&lt;span class="fu"&gt;&amp;lt;*&lt;/span&gt;),pure,(&lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;))&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Char&lt;/span&gt; (&lt;span class="fu"&gt;ord&lt;/span&gt;)&lt;br /&gt;&lt;span class="co"&gt;-- import Text.Parsec (char, oneOf, (&amp;lt;|&amp;gt;), parseTest)&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;-- import Text.Parsec.String (Parser)&lt;/span&gt;&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Attoparsec.Text&lt;/span&gt; (char, &lt;span class="dt"&gt;Parser&lt;/span&gt;, parseTest, satisfy)&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Text&lt;/span&gt; (&lt;span class="fu"&gt;pack&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="ot"&gt;oneOf&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;[&lt;span class="dt"&gt;Char&lt;/span&gt;]&lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Char&lt;/span&gt; &lt;span class="co"&gt;-- attoparsec には oneOf がないので自作&lt;/span&gt;&lt;br /&gt;oneOf xs &lt;span class="fu"&gt;=&lt;/span&gt; satisfy &lt;span class="fu"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;flip&lt;/span&gt; &lt;span class="fu"&gt;elem&lt;/span&gt; &lt;span class="fu"&gt;$&lt;/span&gt; xs&lt;br /&gt;&lt;br /&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Add&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Mul&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt; &lt;span class="fu"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Nat&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="kw"&gt;deriving&lt;/span&gt; &lt;span class="kw"&gt;Show&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;{- BNF of one digit addtion &amp;amp; multiplication&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;expr ::= term ('+' expr | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;term ::= factor ('*' term | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;factor ::= '(' expr ')' | nat&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;nat ::= '0' | '1' | '2' | ...&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;-}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- expr ::= term ('+' expr | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;expr&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;&lt;br /&gt;expr &lt;span class="fu"&gt;=&lt;/span&gt; &lt;br /&gt;  &lt;span class="kw"&gt;do&lt;/span&gt; &lt;br /&gt;    t &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; term&lt;br /&gt;    (&lt;span class="dt"&gt;Add&lt;/span&gt; t &lt;span class="fu"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; (char &lt;span class="ch"&gt;'+'&lt;/span&gt; &lt;span class="fu"&gt;*&amp;gt;&lt;/span&gt; expr)) &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; pure t&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- term ::= factor ('*' term | ε)&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;term&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;&lt;br /&gt;term &lt;span class="fu"&gt;=&lt;/span&gt; &lt;br /&gt;  &lt;span class="kw"&gt;do&lt;/span&gt;&lt;br /&gt;    f &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; factor&lt;br /&gt;    (&lt;span class="dt"&gt;Mul&lt;/span&gt; f &lt;span class="fu"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; (char &lt;span class="ch"&gt;'*'&lt;/span&gt; &lt;span class="fu"&gt;*&amp;gt;&lt;/span&gt; term)) &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; pure f    &lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- factor ::= '(' expr ')' | nat&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;factor&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;    &lt;br /&gt;factor &lt;span class="fu"&gt;=&lt;/span&gt; (char &lt;span class="ch"&gt;'('&lt;/span&gt; &lt;span class="fu"&gt;*&amp;gt;&lt;/span&gt; expr &lt;span class="fu"&gt;&amp;lt;*&lt;/span&gt; char &lt;span class="ch"&gt;')'&lt;/span&gt;) &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; nat&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;-- nat ::= '0' | '1' | '2' | ...&lt;/span&gt;&lt;br /&gt;&lt;span class="ot"&gt;nat&lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt;&lt;span class="dt"&gt;Parser&lt;/span&gt; &lt;span class="dt"&gt;Exp&lt;/span&gt;&lt;br /&gt;nat &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Nat&lt;/span&gt; &lt;span class="fu"&gt;.&lt;/span&gt; charToInt &lt;span class="fu"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; oneOf [&lt;span class="ch"&gt;'0'&lt;/span&gt;&lt;span class="fu"&gt;..&lt;/span&gt;&lt;span class="ch"&gt;'9'&lt;/span&gt;]&lt;br /&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;br /&gt;    charToInt c &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;ord&lt;/span&gt; c &lt;span class="fu"&gt;-&lt;/span&gt; &lt;span class="fu"&gt;ord&lt;/span&gt; &lt;span class="ch"&gt;'0'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="co"&gt;{- How to test this&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;parseTest expr "1+2*3"&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;parseTest expr "(1+2)*3"&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;↓&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;parseTest expr $ pack "1+2*3 "&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;parseTest expr $ pack "(1+2)*3 "&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;※ 最後にスペースがないと、成功していても "Partial _" という出力になる&lt;/span&gt;&lt;br /&gt;&lt;span class="co"&gt;-}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;ghci に load してテストしてみましょう。&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;parseTest expr &lt;span class="st"&gt;"1+2*3"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;うまく行きませんね。あ、String じゃなくて、Text にしないとダメだったかな? pack で String-&amp;gt;Text にしてみます。&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;&amp;gt;&lt;/span&gt; parseTest expr &lt;span class="fu"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;pack&lt;/span&gt; &lt;span class="st"&gt;"1+2*3"&lt;/span&gt;&lt;br /&gt;&lt;span class="dt"&gt;Partial&lt;/span&gt; _&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;あれ、"Partial _" とか言われますね。うまく行ってないのだろうか??? ちょっと末尾に余分なスペースを入れてみよう。&lt;br /&gt;&lt;table class="sourceCode"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lineNumbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }" title="Click to toggle line numbers"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;/pre&gt;&lt;/td&gt;&lt;td class="sourceCode"&gt;&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;&amp;gt;&lt;/span&gt; parseTest expr &lt;span class="fu"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;pack&lt;/span&gt; &lt;span class="st"&gt;"1+2*3 "&lt;/span&gt;&lt;br /&gt;&lt;span class="dt"&gt;Done&lt;/span&gt; &lt;span class="st"&gt;" "&lt;/span&gt; &lt;span class="dt"&gt;Add&lt;/span&gt; (&lt;span class="dt"&gt;Nat&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;) (&lt;span class="dt"&gt;Mul&lt;/span&gt; (&lt;span class="dt"&gt;Nat&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;) (&lt;span class="dt"&gt;Nat&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;))&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;どうやら、直前までは、うまく解析できてるみたい。。よかったー(?)。 今日は、この辺で勘弁してください。attoparsec を深く理解するには、ByteString,Text あたりの知識が必要かも(ByteString, Text については、私もまだ勉強していません)&lt;br /&gt;&lt;h3 id="さらに勉強するための情報源"&gt;(5): さらに勉強するための情報源&lt;/h3&gt;なんとか、Parsec3 と attoparsec を使って、動作するコードを実装し、雰囲気を掴みました。あとは、情報があれば、自分で勉強していけそうです。勉強会, Twitter で、参考になる情報源を紹介していただいたので、ここにまとめてみます。&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://d.hatena.ne.jp/kazu-yamamoto/20101211/1292021817"&gt;あどけない話:Applicativeのススメ&lt;/a&gt; 本記事の元ネタです。Parsec3 の入門記事としても読めます。kazu さんの記事は、どれも非常に参考になります。&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.slideshare.net/RuiccRail/programming-haskell-chapter8"&gt;プログラミングHaskell 8章 関数型パーサ&lt;/a&gt; ruicc 氏による関数型パーサの解説。関数型パーサの考え方についての非常に素晴しい解説資料だと思います。&lt;/li&gt;&lt;li&gt;&lt;a href="http://jonathan.tang.name/files/scheme_in_48/tutorial/parser.html"&gt;Write Yourself a Scheme in 48 Hours&lt;/a&gt; Scheme を実装しながら Parser を学ぶらしい&lt;/li&gt;&lt;li&gt;&lt;a href="http://research.microsoft.com/en-us/um/people/simonpj/papers/pj-lester-book/"&gt;Implementing functional languages: a tutorial&lt;/a&gt; 関数型言語の実装解説&lt;/li&gt;&lt;li&gt;&lt;a href="http://legacy.cs.uu.nl/daan/download/parsec/parsec.html"&gt;Parsec, a fast combinator parser&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cmas60.com/haskell/parser/parsec.php"&gt;還暦プログラマの挑戦(Haskell に挑む→F#による言語造り)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://hackage.haskell.org/package/parsec-3.0.0"&gt;Parsec3&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://hackage.haskell.org/package/attoparsec-0.10.0.3"&gt;attoparsec&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Parsec3 や、attoparsec の使い方について、もう少し詳しい解説記事があると、喜ぶ人が多そうです(私も含めて)。私も上記の文書は、まだ勉強できていませんが、理解が進んだらまた紹介したいと思います。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3963822990972949627-7521319094250694483?l=utotch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://utotch.blogspot.com/feeds/7521319094250694483/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://utotch.blogspot.com/2011/12/haskell-parser.html#comment-form' title='3 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963822990972949627/posts/default/7521319094250694483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963822990972949627/posts/default/7521319094250694483'/><link rel='alternate' type='text/html' href='http://utotch.blogspot.com/2011/12/haskell-parser.html' title='Haskell で parser を書くには (初心者編)'/><author><name>utotch</name><uri>http://www.blogger.com/profile/13699023887797793677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-ATEw_Fx2qWY/TrLC2aSrbuI/AAAAAAACx40/U-3dfXKELdk/s220/kuto_face.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963822990972949627.post-4042102274618707311</id><published>2011-11-30T00:25:00.001+09:00</published><updated>2011-11-30T00:43:29.816+09:00</updated><title type='text'>お絵描き群ロボット</title><content type='html'>ちょっと前になりますが、&amp;nbsp;&lt;a href="http://www.getrobo.com/" target="_blank"&gt;GetRobo&lt;/a&gt;&amp;nbsp;さんが、&lt;a href="http://www.getrobo.com/getrobo_blog/2011/11/4th-getrobo-forum.html" target="_blank"&gt;GetRobo Forum&lt;/a&gt; というイベントを開催され、参加してきました〜。いろんな人と楽しく話しているうちに、ほとんど飲食する暇もなく終了。ロボット関連の方々と交流できた貴重な機会でした。&lt;br /&gt;&lt;br /&gt;そのとき、昔わたしが作った 「お絵描き群ロボット」を紹介したら、結構興味を持ってもらえたので、紹介します。&lt;br /&gt;&lt;br /&gt;「お絵描き群ロボット」は、会社のアイディアコンテストの作品として制作したもので、「iPad に指で曲線を入力すると、その形状に沿って群ロボットが整列する」というものです。こんな感じ↓&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/SzXFGeB6Hxs/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="http://www.youtube.com/v/SzXFGeB6Hxs?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;embed width="320" height="266"  src="http://www.youtube.com/v/SzXFGeB6Hxs?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;制作するのに、どえらい苦労をしたというのにも興味を持ってくれた人がいたので、紹介します。&lt;br /&gt;&lt;br /&gt;&lt;div id="__ss_10384564" style="width: 425px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/utotch/2010-10384564" target="_blank" title="夢卵2010 お絵描き群ロボット 制作編"&gt;夢卵2010 お絵描き群ロボット 制作編&lt;/a&gt;&lt;/strong&gt; &lt;iframe frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/10384564" width="425"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/utotch" target="_blank"&gt;utotch&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;ロボットに興味を持っている人の集まりだったので、結構ウケてくれてうれしかったです。&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&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/3963822990972949627-4042102274618707311?l=utotch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://utotch.blogspot.com/feeds/4042102274618707311/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://utotch.blogspot.com/2011/11/blog-post_30.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963822990972949627/posts/default/4042102274618707311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963822990972949627/posts/default/4042102274618707311'/><link rel='alternate' type='text/html' href='http://utotch.blogspot.com/2011/11/blog-post_30.html' title='お絵描き群ロボット'/><author><name>utotch</name><uri>http://www.blogger.com/profile/13699023887797793677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-ATEw_Fx2qWY/TrLC2aSrbuI/AAAAAAACx40/U-3dfXKELdk/s220/kuto_face.png'/></author><thr:total>0</thr:total></entry></feed>
