(*
* day1.ml
*
*)
(*
* The following example shows how definitions are permanent.
* This is necessary to provide referential transparency.
*)
val y = 6;
fun f(x:int):int = x + y;
f(2);
val y = 4;
f(2); (* same as before *)
(*
* Example of a function (fsum1) that receives another function (f)
* as parameter
* fsum1 returns the sumation of applying f to the integers between
* 1 and m.
*)
fun fsum1(f:(int->real),m:int):real =
let
(* sum is a local helper function *)
(* note that sum is nested inside fsum *)
fun sum(i:int, tot:real):real =
if i > m then (* m is picked from the parent environment *)
tot
else
sum(i+1, tot + (f(i)))
in
(* initial values *)
sum(1, 0.0)
end;
(*
* fsum, another version.
* Does not use a local function.
* Recurses from m down to 0.
*)
fun fsum2(f:(int->real),m:int):real =
if m > 0 then
f(m) + fsum2(f,m-1)
else
0.0;
(*
* fsum, yet another version
* Again, recurses from m down to 0.
* This version uses patterns. Note the | ("or") symbol.
*)
fun fsum3(_, 0):real = 0.0
| fsum3(f:(int->real),m:int) = f(m) + fsum3(f, m-1);
(*
* One, always returns constant 1.0
* Note type 'a, which means ANY type (cool!).
* The simplest form of polymorphism.
*)
fun One(x:'a):real = 1.0;
(*
* Two, always returns constant 2.0
*)
fun Two(x:'a):real = 2.0;
(*
* invocation of fsum
* fsum adds 10 times what One returns (10 times 1)
*)
fsum1(One, 10);
(*
* another invocation of fsum
* This one returns 20 (10 times 2).
*)
fsum1(Two, 10);
(*
* In this invocation of fsum, we define a function.
* It is a function without a name.
* Here it returns the sumation of the squares of integers
* between 1 and 10.
*)
fsum1(fn (k:int) => real(k*k), 10);
(*
* Another invocation of fsum
*)
fsum1(fn (k:int) => 6.0/real(k*k), 10);
(*
* Giving names to functions
*)
(* first an anonymous function (without a name) *)
fn (x:int) => x*x;
(* apply it to an integer *)
(fn (x:int) => x*x) 2;
(* give it a name *)
val square = fn (x:int) => x*x;
(* appply it *)
square 4;
(* now name it using fun, which makes it recursive and adds the
possibility of handling patterns *)
fun square(x:int) = x*x;
(* apply it *)
square(5);
(*
* Example of function composition
*)
(* first, define function square *)
fun square(k:int):real = real(k*k);
(* now, redifine fsum in such a way that the function
can be partially applied *)
fun fsum _ 0 = 0.0
| fsum (f:(int->real)) (m:int) = f m + fsum f (m-1);
(* then define a new function which is the composition of
fsum and square *)
val sumsq = fsum square;
(* and apply sumsq *)
sumsq(4);
               (
geocities.com/htrefftz/mum/cs505)                   (
geocities.com/htrefftz/mum)                   (
geocities.com/htrefftz)