Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 45 lines (37 sloc) 1.535 kB
9fd7471 @maloi th beispiel
maloi authored
1 {-# LANGUAGE TemplateHaskell #-}
2 module PrintF where
3
4 -- NB: printf needs to be in a separate module to the one where
5 -- you intend to use it.
6
7 -- Import some Template Haskell syntax
8 import Language.Haskell.TH
9
10 -- Possible string tokens: %d %s and literal strings
11 data Format = D | S | L String
12 deriving Show
13
14 -- a poor man's tokenizer
15 tokenize :: String -> [Format]
16 tokenize [] = []
17 tokenize ('%':c:rest) | c == 'd' = D : tokenize rest
18 | c == 's' = S : tokenize rest
19 tokenize (s:str) = L (s:p) : tokenize rest -- so we don't get stuck on weird '%'
20 where (p,rest) = span (/= '%') str
21
22 -- generate argument list for the function
23 args :: [Format] -> [PatQ]
24 args fmt = concatMap (\(f,n) -> case f of
25 L _ -> []
26 _ -> [varP n]) $ zip fmt names
27 where names = [ mkName $ 'x' : show i | i <- [0..] ]
28
29 -- generate body of the function
30 body :: [Format] -> ExpQ
31 body fmt = foldr (\ e e' -> infixApp e [| (++) |] e') (last exps) (init exps)
32 where exps = [ case f of
33 L s -> stringE s
34 D -> appE [| show |] (varE n)
35 S -> varE n
36 | (f,n) <- zip fmt names ]
37 names = [ mkName $ 'x' : show i | i <- [0..] ]
38
39 -- glue the argument list and body together into a lambda
40 -- this is what gets spliced into the haskell code at the call
41 -- site of "printf"
42 printf :: String -> Q Exp
43 printf format = lamE (args fmt) (body fmt)
44 where fmt = tokenize format
Something went wrong with that request. Please try again.