Point-free: function as data
(*
compose: ('b -> 'c) * ('a -> 'b) -> 'a -> 'c
*)
fun compose (f, g) = fn x => f(g x)
Point-wise operation
define f +- g
by (f+=g) (x) = f(x) +- g(x)
(*
op ++: ('a -> int) * ('a -> int) -> ('a -> int)
*)
fun ++ (f, g) = fn x => f x + g x
fun ++ (f, g) x = f x + g x
fun MIN (f, g) x = Int.min(f x, g x)
So that we can write these
val a = square ++ twice
val b = MIN(square, twice)
where those are new composed function
Combinator: a small function that is useful for building up functionality from small pieces
Parsing combinators
Alternation: grammar * grammar -> grammar
A slow function
fun f (x : int, y : int) = let
val z = very_slow_computation (x)
in
z+y
end
Another slow function: function g
is only evaluated when both x
and y
are present.
fun g (x : int) (y : int) : int =
let
val z = very_slow_computation (x)
in
z+y
end
in fact while val g5 = g 5
is fast (it just a function with one extra environment binding) but val g57 = g 5 7
is slow. So what is the benifit of using function g
instead f
?
Imagine we need to calculate both val f57 = f 5 7
and val f58 = f 5 8
and very_slow_computation
takes about 1 year. If we are constrained to use function f
or function g
, then if we will at least take 2 years to finish. But if we use function h
. we can first calculate val h5 = h 5
and then calculate val h57 = h5 7
and val h58 = h5 8
, then we can finish in 1 year.
fun h (x : int) : int -> int =
let
val z = very_slow_computation (x)
in
fn y : int => z + y
end
This is good: function h
is evaluated as soon as x
is present.
fun map f l = foldr (fn (x, l') => f x :: l') [] l
fun foldr f b nil = b
| foldr f b (x::xs) = f (x, foldr f b xs)
when f = ::, then it is folding a list
catamorphism: generalized fold
We write our tree fold
(* tfold: ('b * 'a * 'b -> 'b) -> 'b -> 'a tree -> 'b *)
fun tfold f b Empty = b
| tfold f b (Node(l, x, r)) = f (tfold f b l, x, tfold f b r)
building tmap using tfold
fun tmap f T = tfold (fn (l, x, r) => Node(l, f x, r)) (Empty) T
fun tsum (T : int tree): int = tfold (ftold (fun (l, x, r) => l + x + r)) (0) T
fun size (T: 'a tree) : int = tfold (fn (l, x, r) => (l + r+ 1)) 0 T
fun depth (T: 'a tree) : int = tfold (fn (l, x, r) => Int.max(l, r) + 1) - T
Table of Content