Task

Create a function, compose,   whose two arguments   f   and   g,   are both functions with one argument.



The result of compose is to be a function of one argument, (lets call the argument   x),   which works like applying function    f    to the result of applying function    g    to    x.



Example

 compose(f, g) (x) = f(g(x))



Reference: Function composition

Hint: In some languages, implementing compose correctly requires creating a closure.




(*
   The task:
 
      Create a function, compose, whose two arguments f and g, are
      both functions with one argument.
 
      The result of compose is to be a function of one argument,
      (let's call the argument x), which works like applying function
      f to the result of applying function g to x.
 
   In ATS, we have to choose whether to use non-linear closures
   (cloref) or linear closures (cloptr). In the latter case, we also
   have to choose between closures allocated with malloc (or similar)
   and closures allocated on the stack.
 
   For simplicity, we will use non-linear closures and assume there is
   a garbage collector, or that the memory allocated for the closures
   can be allowed to leak. (This is often the case in a program that
   does not run continuously.)
*)
 
#include "share/atspre_staload.hats"
 
(* The following is actually a *template function*, rather than a
   function proper. It is expanded during template processing. *)
 
fn {t1, t2, t3 : t@ype}
compose (f : t2 -<cloref1> t3,
         g : t1 -<cloref1> t2) : t1 -<cloref1> t3 =
  lam x => f (g (x))
 
 
implement
main0 () =
  let
    val one_hundred = 100.0
    val char_zero = '0'
    val f = (lam y =<cloref1> add_double_int (one_hundred, y))
    val g = (lam x =<cloref1> char2i x - char2i char_zero)
    val z = compose (f, g) ('5')
    val fg = compose (f, g)
    val w = fg ('7')
  in
    println! (z : double);
    println! (w : double)
  end