{-# LANGUAGE DataKinds, GADTs, TypeFamilies, TypeOperators #-} module Text.Printf.Safe.Core (type (~>), Formatter, Printf(..), HList(..), printf, printf') where import Data.String (IsString (..)) -- | Variadic function types. type family (~>) as b where (~>) '[] a = a (~>) (x ': xs) a = x -> xs ~> a -- | Formatter type. type Formatter a = a -> String -- | Printf Format. 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 -- | Hetero list. data HList ts where HNil :: HList '[] (:-) :: a -> HList xs -> HList (a ': xs) infixr 9 :-, :<>, :% -- | HList version. 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!" -- | Variadic version. 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)