Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

th beispiel

  • Loading branch information...
commit 9fd747166d91a391de476d62c6130316e046beba 1 parent 3784d5d
maloi maloi authored
Showing with 54 additions and 0 deletions.
  1. +44 −0 PrintF.hs
  2. +10 −0 PrintFMain.hs
44 PrintF.hs
View
@@ -0,0 +1,44 @@
+{-# LANGUAGE TemplateHaskell #-}
+module PrintF where
+
+-- NB: printf needs to be in a separate module to the one where
+-- you intend to use it.
+
+-- Import some Template Haskell syntax
+import Language.Haskell.TH
+
+-- Possible string tokens: %d %s and literal strings
+data Format = D | S | L String
+ deriving Show
+
+-- a poor man's tokenizer
+tokenize :: String -> [Format]
+tokenize [] = []
+tokenize ('%':c:rest) | c == 'd' = D : tokenize rest
+ | c == 's' = S : tokenize rest
+tokenize (s:str) = L (s:p) : tokenize rest -- so we don't get stuck on weird '%'
+ where (p,rest) = span (/= '%') str
+
+-- generate argument list for the function
+args :: [Format] -> [PatQ]
+args fmt = concatMap (\(f,n) -> case f of
+ L _ -> []
+ _ -> [varP n]) $ zip fmt names
+ where names = [ mkName $ 'x' : show i | i <- [0..] ]
+
+-- generate body of the function
+body :: [Format] -> ExpQ
+body fmt = foldr (\ e e' -> infixApp e [| (++) |] e') (last exps) (init exps)
+ where exps = [ case f of
+ L s -> stringE s
+ D -> appE [| show |] (varE n)
+ S -> varE n
+ | (f,n) <- zip fmt names ]
+ names = [ mkName $ 'x' : show i | i <- [0..] ]
+
+-- glue the argument list and body together into a lambda
+-- this is what gets spliced into the haskell code at the call
+-- site of "printf"
+printf :: String -> Q Exp
+printf format = lamE (args fmt) (body fmt)
+ where fmt = tokenize format
10 PrintFMain.hs
View
@@ -0,0 +1,10 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+-- Import our template "printf"
+import PrintF (printf)
+
+-- The splice operator $ takes the Haskell source code
+-- generated at compile time by "printf" and splices it into
+-- the argument of "putStrLn".
+main = do
+ putStrLn $ $(printf "Hello %s %%x%% %d %%x%%") "World" 12
Please sign in to comment.
Something went wrong with that request. Please try again.