ZipN
率直な感想…構文木を作るコード書くのめんどくさすぎ…
自分で書こうと思っても全然書けない。
慣れの問題なのだろうか…?
2004-12-27
「構文木」というのを意識しすぎなのだと思います。
- 例3 任意個のzip
(引用略)
zip3 = $(zipN 3)と書ければ嬉しいという話。
の zipN と zipWithN を書いてみました。
{-# OPTIONS -fth #-} module ZipN where import Language.Haskell.TH zipN n = [| $(zipWithN n) $(tupN n) |] zipWithN n = [| \f x -> $(g (n - 1)) (map f x) |] where g 0 = [| id |] g n = [| \x y -> $(g (n - 1)) (zipWith ($) x y) |] tupN :: Int -> ExpQ tupN n = do nms <- sequence (replicate n (newName "x")) lamE (map varP nms) (tupE (map varE nms))
すごく簡単でしょう?
私は Template Haskell はかなり使いやすくてしかも強力なmeta-programmingシステムだと思います。
捕捉
本当はこれでもいいはずなのだが、存在しないGHC.Tuple.(,,,*)を参照しているというバグのために動作しない。
tupN n = [| $(conE (tupleDataName n)) |]
ghc-6.2.2の場合、newNameがない:
{-# OPTIONS -fth #-} module ZipN622 where import Language.Haskell.THSyntax zipN n = [| $(zipWithN n) $(tupN n) |] zipWithN n = [| \f x -> $(g (n - 1)) (map f x) |] where g 0 = [| id |] g n = [| \x y -> $(g (n - 1)) (zipWith ($) x y) |] tupN :: Int -> ExpQ tupN n = do nms <- gensyms n "x" lamE (map varP nms) (tupE (map varE nms)) gensyms 0 s = return [] gensyms n s = do s' <- gensym s xs <- gensyms (n - 1) s' return (s':xs)