[Haskell-cafe] Re: [Haskell] The initial view on typed sprintf
and sscanf
Ryan Ingram
ryani.spam at gmail.com
Mon Sep 1 04:16:46 EDT 2008
On Mon, Sep 1, 2008 at 1:00 AM, Don Stewart <dons at galois.com> wrote:
> I also wonder if we could give a String syntax to the formatting
> language, using -XOverloadedStrings and the IsString class.
Probably easier with Template Haskell:
> ghci -fth Sprintf.hs
*Sprintf> :t $(sprintf "Hello %s, showing %S and %S")
$(sprintf "Hello %s, showing %S and %S") :: (Show a1, Show a) =>
[Char] -> a -> a1 -> [Char]
*Sprintf> $(sprintf "Hello %s, showing %S and %S") "Don" 1 (5,6)
"Hello Don, showing 1 and (5,6)"
Code follows, which could be ported to use the printf/scanf language
Oleg defined.
-- ryan
{-# LANGUAGE TemplateHaskell #-}
module Sprintf where
import Language.Haskell.TH
data SprintfState =
SprintfState String (ExpQ -> ExpQ)
flush :: SprintfState -> (ExpQ -> ExpQ)
flush (SprintfState "" k) = k
flush (SprintfState s k) = (\e -> k [| $(litE $ StringL $ reverse s) ++ $e |])
finish :: SprintfState -> ExpQ
finish (SprintfState s k) = k (litE $ StringL $ reverse s)
addChar :: Char -> SprintfState -> SprintfState
addChar c (SprintfState s e) = SprintfState (c:s) e
addCode :: ExpQ -> SprintfState -> SprintfState
addCode k s = SprintfState "" (\e -> flush s $ [| $k ++ $e |])
sprintf' :: SprintfState -> String -> ExpQ
sprintf' k ('%':'S':cs) = [| \x -> $(sprintf' (addCode [| show x |] k) cs) |]
sprintf' k ('%':'s':cs) = [| \s -> $(sprintf' (addCode [| s |] k) cs) |]
sprintf' k ('%':'%':cs) = sprintf' (addChar '%' k) cs
sprintf' k (c:cs) = sprintf' (addChar c k) cs
sprintf' k [] = finish k
sprintf :: String -> ExpQ
sprintf = sprintf' (SprintfState "" id)
More information about the Haskell-Cafe
mailing list