Lecture 6.2: More Uses of Functors
Last class, we ended with a type with a user-defined equality function:
This module defines a type with an associated equality: a function which, given two ts, will decide
if they are equal. This allows us to use the type in data structures which assume a given type with a user-defined equality.
Below is our EqType for UnorderedPair:
module UnorderedPair = struct
type t = int * int
let equals p1 p2 =
(fst p1 = fst p2 && snd p1 = snd p2)
||
(snd p1 = fst p2 && fst p1 = snd p2)
end
Now, what if we want a list of unordered pairs? We could implement this directly:
But we would soon see that the complexity ofequals increases dramatically with the size of the type.
Instead, we can use functors to build new EqTypes out of old ones:
module EqTypeList (T : EqType) : (EqType with type t = T.t list) = struct
type t = T.t
let rec equals xs ys =
match xs, ys with
| [], [] -> true
| x :: xs', y :: ys' -> T.equals x y && equals xs' ys'
| _, _ -> false
Here is another for trees:
type 'a tree = | Leaf of 'a | Node of 'a tree * 'a tree
module EqTypeTree (T : EqType) : (EqType with type t = T.t tree) = struct
type t = T.t tree
let rec equals t1 t2 =
match t1, t2 with
| Leaf x, Leaf y -> T.equals x y
| Node (t11, t12), Node (t21, t22) ->
equals t11 t21 && equals t12 t22
| _, _ -> false
end
We can even generalize our unordered pair module:
module UnorderedPairOf (T : EqType) : (EqType with type t = T.t * T.t) = struct
type t = T.t * T.t
let equals p1 p2 =
(T.equals (fst p1) (fst p2) && T.equals (snd p1) (snd p2))
&&
(T.equals (snd p1) (fst p2) && T.equals (fst p1) (snd p2))
end
Then, we can get for free an EqType for unordered pairs of lists of trees that contain integers: