Week 5 reasoning (Part 2): Explanation for Currying, bool*bool, and Sum Types¶
| Subsite home page: | |
|---|---|
| http://bit.ly/focs-aux | |
Isomorphisms:¶
Suppose f is a way to assign a term b in 'b for each term a in 'a, and g is a function that assigns to every term b in 'b a term a in 'a.
f: `a -> `b
g: `b -> `a
Think of f and g as processes. If we have the following conditions then we say f and g are inverses of each other and as a result type 'a and 'b are ismorphic.
f.g = id_`b
g.f = id_`a
The first condition indicates that g is a section and f is a retraction.
If both f and g are sections and retractions then they must be inverses of each other.
Note that composition of functions is defiend as follows:
g.f == fun x -> g (f x)
And identity function is defiend as
let id x = x
Curry and uncurry:¶
This is how we write the code for curry and uncurry functions:
let curry (f: (('a * 'b) - > 'c)) =
fun (a: 'a) ->
fun (b: 'b) ->
f(a,b) ;;
let uncurry (f: ('a -> 'b -> 'c) =
fun ((a,b) : ('a * 'b))-> f a b ;;
check that ::
curry(uncurry f) = id at 'a -> 'b -> 'c
uncurry(curry f) = id at ( 'a * 'b) -> 'c
A good analogy between currying and uncurrying and a law of numerical exponentials: Remember this is only an anology and it’s not a valid O’Caml code:
uncurry (2 ** 3) ** 5 = 2 ** (3 * 5)
curry 2 ** (3 * 5) = (2 ** 3) ** 5
The upshot of this is that currying and uncurrying establish an isomorphism between following types:
('a * 'b) - > 'c and 'a -> 'b -> 'c
Sum type:¶
As in mathematics for any two sets we have union of those two sets, in types we have a corresponding notion. It’s called sum types:
type ('a, 'b) sum =
|left of ('a)
|right of ('b) ;;
There are two functions from product type to sum type:
ProductToSum1 (a,b) = Left a ;;
ProductToSum2 (a,b) = Right b ;;
Convince yourself that there can not be an isomorphism between sum type and product type.
Another Isomorphism¶
There is an isomorphism between the types (bool -> bool) and bool*bool.
In order to establish this ismorphism we need to implement a pair of functions which are inverse of each others; we call them enc and dec for encoding and decoding respectively.
let’s see how we can define the decoding fnction. First, we should specify the type of decoding function:
dec: (bool -> bool) -> bool*bool
And the function itself is defined as
let dec: (bool -> bool) -> bool*bool =
fun (f: bool -> bool) -> (f(false),f(true)) ;;
How about the inverse?
Just by virtue of being the inverse of dec, the function enc can be uniquely defined.
It means that starting from a pair (a,b) of type bool*bool, we should have dec(enc(a,b)) = (a,b).
So, what could enc(a,b) be?
As it should be obviosu to you by now, it is the function f such that f(flase) = a and f(true) = b