module Printf where main = do putStrLn $ printf "%i * %c = %d %s." (2::Integer) 'c' (6.0e8::Double) "meters/sec" putStrLn $ printf "foo is %2$s, bar is %1$s." "bar" "foo" a # b = b a class Printf a where printf :: String -> a printf pat = printf' 0 [] (const id) pat printf' :: Int -> [ShowS] -> ([ShowS] -> ShowS) -> String -> a instance Printf String where printf' n xs k pat = (k xs . showString pat) "" instance (Format a, Printf b) => Printf (a -> b) where printf' n xs k pat = \ x -> break ('%'==) pat # \ (text, ('%':pat')) -> format pat' n x # \ (k', x', rest) -> printf' (n + 1) (xs ++ [x']) (\ xs -> k xs . showString text . k' xs) rest class Format a where format :: String -> Int -> a -> ([ShowS] -> ShowS, ShowS, String) format pat@(c:_) n x | isDigit c = break ('$'==) pat # \ (pos, ('$':pat')) -> format pat' (read pos - 1 :: Int) x format pat n x = format' pat x # \ (f, rest) -> (\ xs -> xs!!n, f, rest) format' :: String -> a -> (ShowS, String) instance Format String where format' ('s':rest) x = (showString x, rest) instance Format Char where format' ('c':rest) x = (showString [x], rest) instance Format Integer where format' ('i':rest) x = (shows x, rest) instance Format Double where format' ('d':rest) x = (shows x, rest)