先週、輪講で「Real World Haskell」の6章を読みました。独自に定義した JSON の型 JValue を Int などへ変換する例題が載っています。このとき、独自に定義した JSON というクラスを使います。
僕は、いや、輪講に参加した全員は、この例題が何を言いたいのかさっぱり分かりませんでした。しかし今日、設定ファイルをどう扱うかを考えていて、ようやく理解できました。
たとえば、設定ファイルを読み込むプログラムを書くとします。設定ファイルは、こんな感じです。
Limit: 10
AllowRootUser: Yes
この設定ファイルをパースする Haskell プログラムは、一つの型しか返せませんから、以下のように Int と Bool を包含する型を作ることになります。
data Config = CV_Int Int | CV_Bool Bool
解析結果は、こんな感じになるでしょう。
[("Limit", CV_Int 10), ("AllowRootUse", CV_Bool True)]
これをプログラムのあちこちで参照することになるのですが、10 や True をいちいちパターンマッチで取り出したくありません。そこで、クラスが出てくるのです。
class Configurable a where fromConf :: Config -> a instance Configurable Int where fromConf (CV_Int n) = n fromConf _ = error "fromConf" instance Configurable Bool where fromConf (CV_Bool b) = b fromConf _ = error "fromConf"
という訳で、fromConf を使えば、文脈に応じて正しい値が取り出せますね!
fromConf (CV_Bool True) :: Bool → True
既存の型を、自分が作ったクラスのインスタンスにするという発想はまったくありませんでしたが、これからはバシバシ使えそうです!