Standard ML
Functions
Side note - operators
A function of two arguments can be treated as an infix operator:
fun d (x,y) = Math.sqrt (x*x + y*y);
Convert to an infix operator using the infix
operator:
infix d;
3.0 d 4.0;
1.0 d 3.0 d 2.0 d 5.0;
operators
The infix declaration can come before the function definition:
infix d;
fun (x d y) = Math.sqrt (x*x + y*y);
To treat an operator as a prefix function use the op
keyword:
op d (1.0,3.0);
Curried functions
Curry = Haskell Curry (1900-1982), who invented the “trick”
Any function of two arguments $(\alpha * \beta)\rightarrow \gamma$
can be expressed as a curried function of one argument $\alpha\rightarrow (\beta \rightarrow \gamma)$
fun prefix (pre, post) = pre ^ post;
The curried version
fun prefix pre = fn post => pre^post;
Reminder: ->
is right associative
val prefix = fn : string -> string -> string
(*is equivalent to*)
val prefix = fn : string -> (string -> string)
partial application
AKA - Partial Evaluation
You don’t have to provide subsequent arguments:
prefix "Dr. ";
it "Watson";
As always, functions are values:
val doctorify = prefix "Dr. ";
doctorify "Jekyll";
currying - syntactic sugar
fun prefix pre post = pre ^ post;
is equivalent to:
fun prefix pre = fn post => pre ^ post;
Invoking a function
(prefix "Dr. ") "Watson";
prefix "Dr. " "Watson";
The rule is:
- a function invocation
F E1 E2 ... En
- abbreviates
(...((F E1) E2)...) En
Example of partial application
Applying infix operator only to one operand
fun add5 y = op+ (5, y);
add5 2;
fun mul5 y = op* (5, y);
Example of partial application
Now, generalize the operator and operand
fun something5 (f:int*int->int) y = f (5, y);
val add5 = something5 op+;
fun intsec x (f:int*int->int) y = f (x, y);
Recursive curried functions
fun times n m =
if m=0 then 0
else n + times n (m-1);
times 4 5;
val times_4 = times 4;
times_4 8;
Function composition operator
infix o;
fun (f o g) x = f (g x);
Math.sqrt o Math.sqrt;
it (16.0);
(fn x => x - ord #"0") o ord;
it #"1";
Questions from exams
What will be printed?
fun f1 a b = f1 a b;
What will be printed?
fun f2 g x = g (f2 g) x;
What will be printed?
fun f3 x y z = (x, x (y), y (z));
What will be printed?
fun f4 f = f f4;