分12この章では,関数型の至宝であるコンビネータライブラリについて説明します。コンビネータとは何か?この章でいうコンビネータとは,ある型の部品と部品を組み合わせて,同じ型のより大きな部品を作るための関数のことです。パーサのコンビネータライブラリは,パーサを組み合わせるための各種コンビネータを提供しており,簡単にパーサを作成できます。Language)と表現してもよいでしょう。関数型では,パーサに加えて,データを文字列でわかりやすく表示するプリティプリンタ,SQL,XML,ハードウェア記述,そしてデリバティブ(金融商品)記述,楽譜記述など多様なコンビネータライブラリが作られ,実際に使われています。この章では,パーサのコンビネータライブラリを取り上げます。CSVのパーサたとえ簡潔でも,実用的でないパーサの例だと興味が持てないでしょうし,一方実用的であっても長いと理解が難しくなるでしょう。そこで,実用的で手頃な大きさで,またみなさんが馴染み深いと思われるCSVのパーサを作ることを考えましょう。4180で定められています(注2⁠)⁠。リスト1に,説明を簡単にするために1行目だけ手を加えたCSVのBNFを示します。%x22*,1*,2はそれぞれ,0回以上,1回以上,2回の繰り返しを意味します。%xは,ASCII文字を16進数表記していることを表します。文法を定める言語のことです。注2)RFCで用いられるBNFは,ABNFというBNFの亜種です。csv,record,fieldの意味これを見ると,csvとはrecordの集まりであり,recordとはカンマで区切られたfieldの集まりであることがわかります。boo,foo,woogoo,zoo,qooたとえば,全体がcsv,boo,foo,wooがrecord,fooがfieldに当たります。これはみなさんの理解通りでしょう。難しいのはfieldです。データ中にカンマや二重符号が出てこない場合はそのままでよいのですが,出てくる場合は二重符号で囲みます。二重符号でカンマを囲むと,区切り文字のカンマと区別がつきます。boo,"foo,woo",goo一方,二重符号に囲まれた二重符号は,囲みなのか二重符号文字そのものなのか区別がつきません。そこで,二重符号を重ねます。boo,"foo""woo",gooこの例の"foo""woo"は,foo"wooを表します。正規表現でCSVパーサを実装する場合みなさんは,CSVパーサを正規表現で実装したくなるかもしれません。CSVパーサを正規表現で作るのは,とても難しいことが知られています。第3版』(⁠注3)の5.4.2項には,CSVパーサを実装した例が載っていますので,興味があれば見てください。正規表現がパーサを作るための技術としてあまり適していない理由は2つあります。第一に,正規表現が入れ子構造を表現できないことです。第二に,正規表現は部品化できないため,正規表現が長くなりがちで,保守しにくくなることです。関数型言語でも正規表現のライブラリは提供されています。簡単な問題であればリスト操作で解決できますし,複雑な問題だとパーサを書きます。そのため,正規表現はあまり使われていません。Friedl著,株式会社ロングテール/長尾高弘訳,オライリー・ジャパン,2008年パーサコンビネータParsecでCSVパーサを実装では,CSVパーサをコンビネータライブラリを用いて実装してみましょう。今回は,Haskellのライブラリの中で,とても有名なパーサのコンビネータライブラリParsecを使用します。Parsecを用いると,BNF通りにパーサを作っていけば,魔法のように目的のパーサができあがります。これから示すコードは,csv.hsというファイルに記述してください(注4⁠)⁠。そのファイルの先頭には,必要なライブラリを読み込むために,次のコードを入れます。Text.Parsec.String今から,CSVのBNFを元にトップダウン的に実装していきます。最後に動かしてみましょう。Vol.67サポートサイトでも完成形を公開しています。csvを実装するまず,BNFのリスト1(1)の部分を実装します。このパターンにはコンビネータendBy1を使います。endBy1は,第二引数で終端される第一引数のパーサを1回以上繰り返すコンビネータです。crlfcsvの型を見てください。Parserとは,パーサというコンテナ型を表しています。このようにパーサをコンテナとして実装するのが常套手段です。このParserというコンテナ同士をくっつけるのがParsecのコンビネータです。内側の型は,Stringのリストのリストになっています。Stringとは[Char]の別名です。外側のリストが行を,内側のリストが列を意味します。CSVファイルをパースした結果は,文字列を要素に持つ二次元のリストになります。recordとcrlfはこれから実装するパーサです。recordを実装する次はリスト1(2)に従いrecordを書きましょう。このパターンには,コンビネータsepBy1が利用できます。sepBy1は,第二引数で区切られる第一引数のパーサを1回以上繰り返すコンビネータです(注5⁠)⁠。comma注5)1回の場合は区切り文字パーサは使われません。fieldを実装する次はfieldです。BNFはリスト1(3)です。/の部分を,選択を表すコンビネータ<|>に単純に置き換えるだけです。開発した代表的なオープンソフトにMew,Firemacs,Mightyがある。『プログラミングHaskell』や『Haskellによる並列・並行プログラミング』の翻訳者。職場ではHaskell,家庭では3人の子供と格闘する日々を送っている。2019」を開催しました。DAY1・DAY2の様子を注目セッションとともにお伝えします。LINEのエンジニア3名がイベントに先駆けて見どころを紹介します。コードの安全性・安定性を高める開発サイクル~テスト管理の効率を上げ,脆弱性診断を自動で行う~本連載では,連載「業務を改善する情報共有の仕掛け」を受けつつ,安全性・安定性を加えた開発サイクルについて考えていきます。若者世代から圧倒的な人気を誇るライブ配信&動画投稿コミュニティアプリ「MixChannel」(ミクチャ)の裏側(レコメンドシステムやサーバサイド開発など)について解説していきます。その他の連載CSS3アニメーションでつくるインターフェイス表現CSS3によるアニメーション表現を紹介していきます。その中でも,幅広い読者に応用してもらえるだろうインターフェイスを主なお題とします。MySQL道普請便り本連載では,MySQLを使ったアプリ開発・運用に関するノウハウをご紹介していきます。RecipeUbuntuの強力なデスクトップ機能を活用するための,いろいろなレシピをお届けします。JavaScriptセキュリティの基礎知識JavaScriptに関するセキュリティ上の問題はどこで発生し,どうすれば防ぐことができるのか?について解説していきます。〜システムをきちんと運用するための基礎知識システムは「作って終わり」ではなく,運用の中でさまざまな問題が発生します。問題の発生に備えて事前にどのような対応をしておくべきなのか,問題発生時に何をしなければならないのか,ポイントを解説していきます。きたみりゅうじの聞かせて珍プレーソフトウェア開発の現場で体験したトホホな失敗,思わずうなる珍プレーをきたみりゅうじ氏が四コママンガで紹介。Linuxのメンテナンスの傍ら,Linuxやオープンソースソフトと日々を過ごす著者が,その魅力とつきあい方を,エッセイ風味でお届けします。PRESS特別編集部員,さわやか笑顔のスーパーハカーはまちちゃんとネット大好き14歳わかばちゃんが,毎号,読者の皆さんから寄せられたおたよりを紹介します。皆さんの日頃の悩みにも答えちゃいますよ。]メールでのお知らせメールで次の案内をお送りしております。メールの配信を希望する方は,利用したい項目をチェックしてメールアドレスを入力し,[登録]ボタンをクリックしてください。UPDATES[ほぼ週間に1回]新刊メールマガジン[ほぼ週間に1回]電脳会議の各号案内[ほぼ1ヵ月半に1回]※変更する場合や停止する場合は,登録情報変更ページをご覧ください。※登録いただいたメールアドレスには,そのお知らせ以外,配信いたしません。Ltd.ページ内容の全部あるいは一部を無断で利用することを禁止します。個別にライセンスが設定されている記事等はそのライセンスに従います。