Haskell導入前の検討 あとこのへんのunixとかfilepathとかdirectoryとかprocessとかって、もうコンパイラにライブラリが入っているんですよね。だから、GHCさえ入っていれば絶対使えるんですよ。 だからそういう面倒くささがないなと思って。いろんなライブラリを入れなきゃいけないということも、このぐらいだったらあんまりないだろうと思って。いよいよ2010年ぐらいから導入しだしました。 すごいですよこれ！ むちゃくちゃ古いですよ！ みなさんもうわからないんじゃないですかね。Debian lennyとかもう知らないでしょ？ Debian 5.0です。5.0！ あと、GHC6.8ですから！ 8.6じゃないですからね？ 6.8ですから！ （会場笑） 6.8です。ヤバイ！ cabal installがこの頃なかったんですよ。すごくないですか!? （会場笑） まあそれはそれとして。でも、別に小さいプログラムを書くだけだったら大したことないので。 新しく書く部分はもうどんどんPerlで書くのをやめてHaskellにしていって。まぁ私1人でなんですけど。でも、ファイル操作とかJavaをひたすら呼び出すとかそんなのばっかりなので、けっこう簡単なプログラムですね。 1人なんですけど、Haskellのプログラムはあんまり大きくないので、アプリの本数に比べて行数がぜんぜん少ないんですね。アプリ16個で2,700行とか、アプリ22本で5,800行とか、そんな感じなんですけど。あんまり大きくないです。 あとは、Perlで書いてる頃よりだいぶ精神的負荷が下がりましたよね。

Haskellを導入して書きやすくなったもの それはそうと、最初はバッチプログラムを呼び出すプログラムとか書いてたんですけど、ちゃんと使えるのでだんだんいろんなことに使い始めて。それもほとんど全部私がやってたんですけど。 だから、ふだんから仕事で使っててやっぱり感動したのは、Parser Combinatorが使いやすさですね。 ISPとかだと変なテキスト処理がいっぱいあるんです。とにかくよくわからない整理されていないログがいっぱいあるので、そこから無理やり必要な情報を取り出すはめになるみたいのがけっこう多くて。 Parser Combinatorはここに書いてあるような……山ほどくるトラフィックデータを全部加工してDBに突っ込んだり、社内のIRCがやたらめったらチャンネル立っているのをログを検索したいとかって言われて、一生懸命それ用に加工したり。 そうですね、接続ログ。みなさんがプロバイダとかでこのフレッツとかプロバイダを使うときに、「PPPoEで認証して」みたいな認証ログがものすごい数あるんですけど、そいつを集計するプログラムをHaskellで作りました。 このAttoparsecは、当時Parsecよりだいぶ高速に動作するParser Combinatorとして有名で、この速度に助けられたこともあります。 あと、いろいろトラブルが起きるんですけど、そうすると、実際なにが起きたのかをログから解析しなきゃいけなくて、そういったことを抜き出す仕事もいっぱいありましたが、これもすごい助かりました。 あと、認証バックエンドを作った時に、古い認証サービスの認証データを加工して新しい認証サービスに入れたりする時とかに使いました。 ビルドシステムもHaskellで書きました。 実は前職のISPはバックエンドのリレーショナルデータベースでDB2を使ってたんですけど、そのDB2のパッケージをIBMから配られているDebian用に変換するプログラムを書いて、それ全部ビルドするみたいな。 あと、内製のHaskellライブラリもいっぱい作ったので、それを全部Debianパッケージに変換するプログラムを書いたりしました。全部ビルドすると、気がついたら40分ぐらいかかるようになりました。びっくりしましたけど。 認証バックエンドの認証サーバを作ったんです。Haskellって Software Transactional Memory（ STM）が簡単に使えるので、状態のあるマルチスレッドプログラムがすごい書きやすくて助かりました。

マルチスレッドとDSLについて オープンリゾルバ検出システム、これけっこうおもしろかったんですけど。 実はISPのお客様にオープンリゾルバの方がいっぱいいらっしゃって、「どのぐらいいるんだろう？」と思って探しにいくというプログラムを書いていた。これもDNSクエリーするコマンドを呼び出すだけのすごい並列度の高いプログラムで、たぶん今でも毎日900並列ぐらいで動いているんじゃないかと思います。 あとは、バックエンドの接続認証サーバはやっぱりマルチスレッドのものを書きました。こういうものが書きやすかったんですね。 あと、やっぱりDomain Specific Language（DSL）ですね。 解こうとした問題に合ったDSLを定義するみたいのは、やっぱりHaskellはけっこうやりやすいんじゃないかと私は思っていて。なんといっても、まずMonadが入ってたりするんですけど。実際どういうふうに使うかみたいのは、今日はあまり詳しく説明できないですけど。 あと、私が作ってるHaskell Relational Recordってライブラリがあって。これはSQLを組み立てるDSLなので、これを使ってデータベースのトランザクション処理みたいなのを書いて、実際に債権データの集計処理とか、さっき言った認証サービスのバックエンドのデータ管理のシステムとかを作りました。 では、ここらへんで一応導入した話のまとめです。 まず、Glue言語の置き換えとしてHaskellを導入しました。書きやすかったのは、テキスト処理とかプロセス制御とかマルチスレッドとか、あとDSLだったという話でした。

Haskell Relational Recordの紹介 ここから後半で、Haskell Relational Recordの紹介なんですけど。これは入門者向けの内容じゃなくなってるかもしれないので、注意事項という感じなんですけど。あんまり厳密な「どういうふうに動いているんだ？」みたいのはとりあえず気にしなくても大丈夫です。ただ、SQLがわからないと厳しいかもしれません。 要するにHaskellのコードとSQLが対応づいている、みたいなのが今日出てくる予定です。なのでそれがなんとなくわかれば、細かいところは気にしなくていいと思います。実際DSLって、そういうふうに適当に書くと、うまく展開されて、なんかいい感じになる、というためのものなので。 一応このURLがプロジェクトページになりまして、「SQLを組み立てるHaskell内DSL」、Haskell Relational Recordライブラリです。 売りは部品化と型安全です。だから、なにか小さいクエリを組み合わせて、より複雑な大きいクエリを作ることができて、部品化がちゃんとできていて、あと部品を組み合わせるときに型をチェックするので、変なものが変なところに組み合わさっても、誤りがあればコンパイル時に発見できるでしょうという感じです。 あと、実はコンパイル時にTemplate Haskellのマクロの機能を呼んで、Database Schemaをデータベースから読んできて、それに合った型定義を生成するので、データベース側ともだいたい型が合っていることがわかります。 このライブラリは2013年ぐらいから開発してました。

SQLの結合と集合演算 いきなりですが、SQLのJOIN（結合）ですね。 これがどういうものかという話なんですけど、これほとんど説明がなにも書いてないですけど。今「person」というテーブルと「birthday」というテーブルがあって、「person」にはnameとageとfamilyが入ってて、「birthday」にはnameとdayいうふうに入っているんですね。こいつをJOINしました。 これはこういう集合演算です。数式アレルギーの人はうんざりする話なんですけど、数式だとこういうものだと思ってください。だからpersonの集合から1個取って、birthdayの集合から1個取って、その1個取ったやつのnameを取り出してるのが等しいようなやつだけ、組を全部集めてくださいって言ってるわけですね。 SQLはこの数式を書こうとしてるんですよ。たぶん……、というか最初に考えた人はそう考えたと思ってて。 Haskellはこの数式に似た記法があるんですよね。例えば「List内包表記」というのがそれで、集合のこの「∈」のところの記号と、この「<-」のですね。「似てるでしょ？」みたいな。まぁ、気分だと思うんですけど。 このリストから1個取り出して、そいつのnameというフィールドが等しくなっていれば、こんだけ全部リストにして返してくださいというのが「List内包表記」ですね。 それで、見た目はちょっと違うけど、これとまったく意味が同じものをdoで書けるんですよ。まったく同じなので読み替えるだけです。この中がどうなったかは気にしなくてもいいんです。

Haskellを使ったDSL 「これと同じようにSQLを組み立てられたらいいんじゃない？」と思ってやってみました。 ゴテゴテしてますけど、personから1個取り出して、birthdayから1個取り出して、そいつのnameというフィールドを取り出したやつを、その結果の2つをくっつけて返してみたいなものが、このList内包表記と同じような、Listモナドと同じようなことをやるクエリがほしいなと思って作ったら、こんなふうになりました。 だから、こういうふうに書くと実はこういうSQLが生成されると。 こうやって定義したやつを展開すると、こういうSQLが生成されます、みたいな。だから、SQLをあんまり知らなくても、もしかして書けちゃうかもしれないみたいな感じのやつです。 このpersonのnameとかbirthdayのnameとかを選ばせるのが面倒くさいという人が多いので、最近は「もうnameというフィールドがあればいいんだろう」みたいなふうに書ける機能が増えたりしました。最近はこれが短くなった。 こうすると型がわかりにくくなることがあるんです。だからこれは一応トレードオフがあるんですよね。なので、みなさん書いてて、「型が決まらなくてびっくり！」みたいなことがあるかもしれないですけど、そういうときは元の書き方とかで工夫してみてください。