2008-03-07
$(tGen ''SomeState) → data SomeStateT m a = ...
StateTをnewtypeでラップする手順を長々と日本語で書いた(id:illillli:20080228#p1)が、TemplateHaskellでプログラムにしたほうが早いことに気づいた。
まだStateでラップする部分しか書いていない。ここまででいくつかTemplateHaskellの問題に気づいた。
- [t| .. |](型の準クォート)や[d| .. |](宣言の準クォート)の中では展開が使えない
このため、全体的に宣言を生成するのが面倒だった。
例えばこう書けるはずのところを
[d| newtype $fooT m a = $conFooT { $runT :: StateT $foo m a } deriving (Functor, Monad, MonadIO, MonadTrans) |]
こう書かねばならなかった。
let tvars = map mkName ["m", "a"] [m, a] = map varT tvars newtypeD (cxt []) fooT tvars (recC conFooT $ [varStrictType runT $ strictType notStrict $ apps [conT ''StateT, foo, m, a]]) [''Functor, ''Monad, ''MonadIO, ''MonadTrans]
検索して出てきた話では、[d|は括弧の中で複数の宣言ができるので、スコープの問題が出てくるそうだ。Q [Dec]じゃなくてQ Dec用の括弧を作ればいいと思うのだが、議論をそれ以上読んでいない。[t|の方は修正があるらしい。
- GHCのderivingの拡張に対応していない
data Dec = ... | DataD Cxt Name [Name] [Con] [Name] | NewtypeD Cxt Name [Name] Con [Name]
それぞれ最後の[Name]がderiving節に当たる。これはつまりTemplateHaskellではderiving節にMonadState SomeStateと書けないということだ。
> runQ [d| newtype A m a = A (StateT Int m a) deriving (Monad, MonadState Int) |] <interactive>:1:5: Non-H98 deriving clause not (yet) handled by Template Haskell MonadState Int
仕方なくインスタンス化の宣言を別に書くようにしている。MonadReaderも同じことをしないといけないので少し意気消沈気味。
コメントを書く
トラックバック - http://haskell.g.hatena.ne.jp/illillli/20080307