Matthew Brecknell wrote:
Unfortunately, I don't seem to be able to make the expected fprintf
function, because printf's format-dependent parameter list makes it
impossible to find a place to pass the handle. Hence the C++-like (<<)
ugliness.


How about this:

fprintf :: Handle -> F (IO ()) b -> fprintf h fmt = write fmt id where
  write :: F a b -> (IO () -> a) -> b
  write (FLit str) k = k (hPutStr h str)
  write FInt k = \i -> k (hPutStr h (show i))
  write FChr k = \c -> k (hPutChar h c)
  write (FPP (PrinterParser pr _)) k = \x -> k (hPutStr h (pr x))
  write (a :^ b)  k = write a (\sa -> write b (\sb -> k (sa >> sb)))

*PrintScan> fprintf stdout fmt5 15 1.3 '!'
abc15cde1.3!*PrintScan>

The first thing I did last night was change String to
type ShowS = String -> String :

intps :: F a b -> (ShowS -> a) -> b
intps (FLit str) k = k (str++)
intps FInt       k = \x -> k (shows x)
intps FChr       k = \x -> k (x:)
intps (FPP (PrinterParser pr _))  k = \x -> k (pr x ++)
intps (a :^ b)   k = intps a (\sa -> intps b (\sb -> k (sa . sb)))

sprintfs :: F ShowS b -> b
sprintfs fmt = intps fmt id

Ideally PrinterParser would display using "ShowS" as well:

data PrinterParser a
  = PrinterParser (a -> ShowS) (String -> Maybe (a, String))

Or one could use instance witnesses via GADTs to wrap up Show:

data F a b where
    FSR  :: (Show b,Read b) => F a (b -> a)

But I think changing PrinterParser would result in simpler code.

Cheers,
  Chris

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to