[MLton] handling a variable number of arguments in SML
   
    Stephen Weeks
     
    MLton@mlton.org
       
    Tue, 23 Aug 2005 15:48:12 -0700
    
    
  
> the simplest version I could come up with, which shows how to define
> a function "f" that takes a variable number of "a" arguments, and
> when it receives the end of arguments marker, "$", returns the
> number of "a"s it received.
The approach can be generalized to allow one to define a fold
function that takes a variable number of arguments.
----------------------------------------------------------------------
signature S =
   sig
      type ('a, 'b, 'k) v
      type ('a, 'b, 'k) u = ('a, 'b, 'k) v -> 'k
      val $ : ('a, 'b, 'b) v
      val fold: 'b * ('a * 'b -> 'b) -> ('a, 'b, 'k) u
      val a: 'a -> ('a, 'b, ('a, 'b, 'k) u) v
   end
functor F (S: S) =
   struct
      open S
      fun p i = print (concat [Int.toString i, "\n"])
      val () = p (fold (0, op +) (a 1) (a 2) (a 3) $)
   end
  
structure S: S =
   struct
      type ('a, 'b, 'k) v = 'b * ('a * 'b -> 'b) -> 'k
      type ('a, 'b, 'k) u = ('a, 'b, 'k) v -> 'k
      fun $ (b, _) = b
      fun fold z v = v z
      fun a x (b, f) v = v (f (x, b), f)
   end
structure Z = F (S)
----------------------------------------------------------------------
This has one advantage over the usual List.fold because MLton will
simplify away all the continuation stuff and will thus be encourage to
compute the fold at compile time.  For example, in the above, I would
bet that the sum, 6, is computed at compile time.
I'm unsure of what advantage, if any, the continuation approach has
over the composition-of-arguments approach.
----------------------------------------------------------------------
infix 4 &
signature S =
   sig
      type ('a, 'b) arg
      val & : ('a, 'b) arg * ('a, 'b) arg -> ('a, 'b) arg
      val fold: 'b * ('a * 'b -> 'b) -> ('a, 'b) arg -> 'b
      val a: 'a -> ('a, 'b) arg
   end
functor F (S: S) =
   struct
      open S
      fun p i = print (concat [Int.toString i, "\n"])
      val () = p (fold (0, op +) (a 1 & a 2 & a 3))
   end
  
structure S: S =
   struct
      type ('a, 'b) z = 'b * ('a * 'b -> 'b) 
      type ('a, 'b) arg = ('a, 'b) z -> ('a, 'b) z
      val op & = op o
      fun fold z (v: ('a, 'b) arg) = #1 (v z)
      fun a x (b, f) = (f (x, b), f)
   end
structure Z = F (S)
----------------------------------------------------------------------