reflectionを使ったテクニック

reflectionというライブラリを使って、ちょっと便利なものを思いつきました。 これです

何をするものかと言うと、forall a. Show a => Show (f a)と書けるShowのインスタンスを持つ型fに対して、 Show1 fを機械的に定義できるようにするモジュールです。

-- | Automatic Show1(liftShowsPrec) 
autoLiftShowsPrec
  :: (Functor f)
  => (forall a. Show a => Int -> f a -> ShowS)
  -> (Int -> b -> ShowS)
  -> ([b] -> ShowS)
  -> Int -> f b -> ShowS

-- | Automatic Show1(liftShowList) 
autoLiftShowList
  :: (Functor f)
  =>  (forall a. Show a => [f a] -> ShowS)
  -> (Int -> b -> ShowS)
  -> ([b] -> ShowS)
  -> [f b] -> ShowS

data F a = ...
    deriving (Show, Functor)

instance Show1 F where
    liftShowsPrec = autoLiftShowsPrec showsPrec
    liftShowList = autoLiftShowList showList

Genericsが不要なことと、reflection以外のライブラリに依存しないことがウリです。 また、同じ手法でShow2,Read1, Read2もできます。残念ながら(Eq|Ord)(1|2)は無理です。

もしかしたらライブラリとしてすでに存在するのかもしれませんが、ちょっと探しきれなかったのでここで公開してみます。 要望があればちゃんとしたパッケージにします。