data I f = I f; data C f = C f; data S f = S (List Char) f; class Format fmt where { type Sprintf fmt; sprintf' :: List Char -> fmt -> Sprintf fmt; } instance Format (List Char) where { type Sprintf (List Char) = List Char; sprintf' prefix str = prefix ++ str; } instance Format a => Format (I a) where { type Sprintf (I a) = Int -> Sprintf a; sprintf' prefix i = case i of I a -> (\j -> sprintf' (prefix ++ show j) a);; } instance Format a => Format (C a) where { type Sprintf (C a) = Char -> Sprintf a; sprintf' prefix c = case c of C a -> (\d -> sprintf' (prefix ++ show d) a);; } instance Format a => Format (S a) where { type Sprintf (S a) = Sprintf a; sprintf' prefix s = case s of S str a -> sprintf' (prefix ++ str) a;; } sprintf :: Format fmt => fmt -> Sprintf fmt; sprintf = sprintf' ""; formatSpec = S "Int: " (I (S ", Char: " (C "."))); main = sprintf formatSpec 42 'S';