はじめてのTemplate Haskell

PDFを6ページくらい読んだところ。英文読んでると寝てしまう。なんでだろ。

> ghc --make -fth Main.hs -o main
> ./main "World\!"
"Hello, World!"
"1 2 3 4"
{-
    Main.hs
    -fth
    http://research.microsoft.com/~simonpj/papers/meta-haskell/
    nisikawa
    2007.05.20
-}
module Main where

import System (getArgs)
import Print (printf)

main = do
  (name:_) <- getArgs
  print ($(printf "Hello, %s") name)
  print ($(printf "%d %d %d %d") 1 2 3 4)
{-
    Print.hs
    -fth
    http://research.microsoft.com/~simonpj/papers/meta-haskell/
    nisikawa
    2007.05.20
-}
module Print where

import Language.Haskell.TH
import Text.ParserCombinators.Parsec

data Format = S | D | L String deriving Show

run s = case parse myParser "print" s of
            Left err -> error $ show err 
            Right x  -> x

myParser = do
  x <- lineParser <|> return (L "") 
  case x of
    L ""      -> return []
    otherwise -> do y <- myParser; return (x:y)

lineParser = (try (char '%' >> choice [s, d, o]))
             <|> (try (many1 (noneOf "%")) >>= \x -> return (L x)) 
  where s = char 's' >> return S
        d = char 'd' >> return D
        o = anyChar >>= \x -> return (L ('%':[x]))

gen :: [Format] -> ExpQ -> ExpQ
gen []        x = x 
gen (D  : xs) x = [|\n -> $(gen xs [|$x ++ show n|])|]
gen (S  : xs) x = [|\s -> $(gen xs [|$x ++ s|])|]
gen (L s: xs) x = gen xs [|$x ++ $(stringE s)|]

printf :: String -> ExpQ
printf s = gen (run s) [|""|]