[MLton] printf with no infixes

Stephen Weeks MLton@mlton.org
Wed, 24 Aug 2005 21:35:03 -0700


The latest varargs hack that I sent yesterday can be used to improve
printf so that no infix operators are needed.  The code is below.  I
think there is still room for a couple of improvements, namely: avoid
the intermediate list construction (presumably using continuations)
and allow the expression of other varargs functions with non-unit
result types, e.g. format.

----------------------------------------------------------------------

signature PRINTF =
    sig
       type ('a, 'b, 'c) v
       type ('a, 'b, 'c) u = string -> ('a, 'b, 'c) v -> 'c
       type ('x, 'a, 'b, 'c) f = ('x -> 'a, 'b, ('a, 'b, 'c) u) v

       val $ : (unit, 'b, 'b) v
       val D: (int, 'a, 'b, 'c) f
       val G: (real, 'a, 'b, 'c) f
       val S: (string, 'a, 'b, 'c) f
       val newFormat: ('x -> string) -> ('x, 'a, 'b, 'c) f
       val printf: ('a, 'a, 'b) u
    end

functor F (S: PRINTF) =
   struct
      open S

      val () = printf "Hello.\n"$
      val () = printf "An int "D" and an int "D".\n"$ 13 14
      val () = printf "An int "D" and a real "G".\n"$ 13 3.1415
      val () = printf "A real "G" and a real "G".\n"$ 13.1 3.1415
   end

structure Printf: PRINTF =
   struct
      type 'a k = string list -> 'a
      type ('a, 'b, 'c) v = string * ('a k -> 'b k) -> 'c
      type ('a, 'b, 'c) u = string -> ('a, 'b, 'c) v -> 'c
      type ('x, 'a, 'b, 'c) f = ('x -> 'a, 'b, ('a, 'b, 'c) u) v

      fun printf s f = f (s, fn k => k)

      fun $ (s, m) = m (fn ss => List.app print (rev (s :: ss))) []

      fun newFormat toString (s, m) s' f =
         f (s', fn k => m (fn ss => fn x => k (toString x :: s :: ss)))

      val C = fn z => newFormat Char.toString z
      val D = fn z => newFormat Int.toString z
      val G = fn z => newFormat Real.toString z
      val S = fn z => newFormat (fn s => s) z
   end

structure Z = F (Printf)