Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Lecture 9
Stephen Brookes
Polymorphism
Functions as values
Higher-order functions
MEDIAN
15-150 Homeworks
96
93.75
91.5
89.25
87
HW01
HW02
HW03
Previously
Types and the type guarantee
Polymorphic types and their instances
Rules for type checking or inference
If e has type t and e =>* v
then v is a value of type t
polymorphic values?
What are the values of type a list
Only [ ]
typability
t is a type for e
from the
inference rules
fun rev [ ] = [ ]
| rev (x::L) = (rev L) @ [x]
int list -> int list
is a type for
rev
is a type for
is a type for
rev
rev
Instantiation
If e has type t, and t is an instance of t,
then e also has type t
has type
int * bool
type inference
ML computes most general types
statically, using syntax as guide
Standard ML of New Jersey v110.75
-
fun rev [ ] = [ ] | rev (x::L) = (rev L) @ [x];
val rev = fn : 'a list -> 'a list
datatypes
ML allows parameterized datatypes
datatype a tree = Empty
| Node of a tree * a * a tree
a type constructor tree
and polymorphic value constructors
Empty : a tree
Node : a tree * a * a tree -> a tree
example
fun trav Empty = [ ]
| trav (Node(t1, x, t2)) = (trav t1) @ x :: (trav t2)
declares trav : a tree -> a list
options
datatype a option = NONE | SOME of a
fun try (f, [ ]) = NONE
| try (f, x::L) = case (f x) of
NONE => try (f, L)
| SOME y => SOME y
try : (a -> b option) * a list -> b option
equality
ML allows use of = only on certain types
These are called equality types
int
example
fun mem (x, [ ]) = false
| mem (x, y::L) = (x=y) orelse mem (x, L)
declares mem : a * a list -> bool
OK instances include
int * int list -> bool
(int list) * (int list) list -> bool
but not real * real list -> bool
And now
Functions as values
Higher-order functions
The power of polymorphism
Math problem
For real numbers a < b,
there is a linear function f : real -> real
such that
f(a) = ~1.0
f(b) = 1.0
Given a and b, find f.
ML version
A function
norm : real * real -> (real -> real)
such that for all a, b : real with a < b,
norm(a, b) =>* a linear function f
satisfying
f(a) = ~1.0 and f(b) = 1.0
calculate , such that
*a + = ~1.0 and *b + =1.0
norm
fun norm(a, b) = fn x => (2.0 * x - a - b) / (b - a)
norm
Let a < b
For all x such that
a x b,
~1.0 norm(a, b) (x) 1.0
and
norm(a, b)
norm(a, b) a = ~1.0
norm(a, b) b = 1.0
normalizes the real interval [a...b]
using norm
Given a pair of reals,
first attempts
fun normpair(a, b) =
fn (x,y) => (norm(a,b) x, norm(a,b) y)
or, better,
fun normpair(a, b) =
fn (x, y) => let
val f = norm(a,b)
in
(f x, f y)
end
critique
We often need to apply a function to
components of a data structure
general problem
For pairs, we want a generic way to
solutions
For pairs, a polymorphic function
pair spec
pair : (a -> b) -> (a * a -> b * b)
(* REQUIRES true
(* ENSURES pair f (x, y) = (f x, f y)
*)
*)
pair
fun pair f = fn (x, y) => (f x, f y)
pair : (a -> b) -> (a * a -> b * b)
pair(norm (~2.0, 2.0)) : real * real -> real * real
map spec
map : (a -> b) -> (a list -> b list)
(* REQUIRES true
(* ENSURES For all n0,
map f [x1, ..., xn] = [f x1, ..., f xn]
*)
*)
map
map f R = (map f) R
fun map f [ ] = [ ]
| map f (x::R) = (f x) :: (map f R)
map : (a -> b) -> (a list -> b list)
map (norm(~2.0, 2.0)) : real list -> real list
map (norm(~2.0, 2.0)) [1.0, 1.5. 2.0] =>* [0.5, 0.75, 1.0]
map
map f R = (map f) R
fun map f [ ] = [ ]
| map f (x::R) = (f x) :: (map f R)
syntactic sugar
fun F p11 p12 = e1
| F p21 p22 = e2
...
| F pk1 pk2 = ek
declares F : t1 -> t2 -> t
if for each i, pi1 fits t1, pi2 fits t2, and
they produce type bindings for
which, assuming F : t1 -> t2 -> t,
ei has type t
so far
using map