module Text.Printf.Safe.Core (type (~>), Formatter, Printf(..),
HList(..), printf, printf') where
import Data.String (IsString (..))
type family (~>) as b where
(~>) '[] a = a
(~>) (x ': xs) a = x -> xs ~> a
type Formatter a = a -> String
data Printf xs where
EOS :: Printf '[]
(:<>) :: String -> Printf xs -> Printf xs
(:%) :: Formatter x -> Printf xs -> Printf (x ': xs)
instance (xs ~ '[]) => IsString (Printf xs) where
fromString str = str :<> EOS
data HList ts where
HNil :: HList '[]
(:-) :: a -> HList xs -> HList (a ': xs)
infixr 9 :-, :<>, :%
printf' :: Printf ts -> HList ts -> String
printf' ps0 ts0 = go ps0 ts0 ""
where
go :: Printf us -> HList us -> ShowS
go EOS HNil = id
go (str :<> fs) xs = showString str . go fs xs
go (fm :% fs) (x :- ds) = showString (fm x) . go fs ds
go _ _ = error "bug in GHC!"
printf :: Printf xs -> xs ~> String
printf p = go p ""
where
go :: Printf xs -> String -> xs ~> String
go EOS a = a
go (str :<> xs) a = go xs (a ++ str)
go (fmt :% xs) a = \x -> go xs (a ++ fmt x)