はじめに

BIG MOON では、業務に必要なツールを自社開発しており、プログラミング言語に Haskell を採用しています。実用的に利用し始めて3年ぐらい?です。

僕らが Haskell を利用していて一番困った点はレコードの取り扱いです。

  • 異なる型のフィールドラベルに同じ名前を付けたい
  • フィールド全体対して関数を適用したい
  • フィールド多相な関数を定義したい

このような問題に対して extensible という、(当初は謎に包まれていた) パッケージの利用を検討し、実際に既存のシステムを extensible で置き換えました。(当時アルバイトしていた matsubara0507 さんが居なければ実現不可能だったと思います)

今回、縁あって作者の fumieval さんと一緒に仕事できる機会に恵まれました。fumieval さんは簡単な質問でも、とても気さくに答えてくれます。

僕達のノウハウはまだまだとても少ないですが、この素晴らしいパッケージを広く知って欲しいと思い、まだまだ作成途中ではありますが extensible 攻略Wiki という親しみやすい雰囲気で情報を発信していくことになりました。

この wiki もまた Haskell で作られており apus という名前で公開されています。

今回の extensible-0.4.9 のアップデートは、攻略wiki のコンテンツを拡充していく中で出てきたアイデアや、関数などがいくつか追加されました。(matsubara0507 さんと弊社も色々と貢献できているはずです!)

今回はその内容について簡単な例とともに解説を行いたいと思います。

アップデート内容

以降の例では、上記の Person 型と person 変数が宣言されているものとします。


  • MonadIO のインスタンスを一般化しました。

ベースモナドとして ResourceT IO などが使えるようになりました。

今までは Associate "IO" (ResourceT IO) のように書けませんでしたが、こんな感じのコードが書けるようになりました。また、ResourceT IO 以外にも MonadIO のインスタンスであれば何でも指定可能です。

ここでは MonadResource のインスタンスを自分で定義しましたが、次回リリース (0.4.10) でライブラリに追加される予定?です。(たぶん)

ただ単に csv ファイルを読み込んで表示するだけの例です。

-- data.csv
"bigmoon", 10, "watch"
"wado", 100, art

完全なコード


  • 新しい制約コンビネータ And を追加しました。

このコンビネータを利用することで Forall の制約を二つ以上指定することができます。

以下は拡張可能レコードの値が Show かつ Typeable の両方を満たすという制約で hfoldMapFor 関数を使う例です。

例として定義した debug 関数は与えられた拡張可能レコードの を表示することができます。

完全なコード


この関数を使えば、拡張可能レコードのキーを文字列として取得することができます。

例えば、拡張可能レコードのキーを全て集めてリストにして返す関数は以下のように作ることができます。

IsString のインスタンスであれば何でも良いので、String に限らず Text, ByteString などを返すことができます。

完全なコード


  • prettyprinter パッケージの Pretty のインスタンスを追加しました。

prettyprinter パッケージについては過去のブログ記事で少し紹介しているので、興味ある方はそちらをご確認ください。

以下のような出力になるそうです。

現状は prettyprinter 側のバグ?で上手く表示されていないようですが、そのうち直ると思います。

完全なコード


  • th-liftLift のインスタンスを追加しました。

Lift のインスタンスになったので例えば、Data.Yaml.TH モジュールの decodeFile 関数を使ってコンパイル時に yaml ファイルから一気に拡張可能レコードを作り上げることができます。

実行例:

完全なコード


hmapWithIndex の制約付きバージョンです。

例えば以下のようにして拡張可能レコードから aeson パッケージの Value をフィールドとして持つ拡張可能レコードに変換できます。

実行例:

完全なコード


  • Const’ に Monoid のインスタンスを追加しました。

  • Wrapper に Either e のインスタンスを追加しました。

まとめ

extensible パッケージは初見では全く使い方がわからないレベルで難しいですが、実際に使ってみると、今までリアルワールド Haskell っぽいコードだね。仕方ないね。と妥協していた部分がとても綺麗に書けるようになります。

extensible 攻略Wiki の内容はこれからもっと充実して行くので、気になる人はチェックしてみてください!