The eq function is the cannonical example of a polytypic function. Let's consider how eq looks for each of the datatypes introduced in the previous section.
For D and C the eq functions are the obvious
implementations. We just present the types of the functions here:
eqD :: D D
Bool
eqC :: C C
Bool
For M and L the eq functions are again
obvious, but require an auxilary equality function for testing the
equality of the polymorphic data. We just present the types of the
functions here:
eqM :: (
Bool)
M
M
Bool
eqL :: (
Bool)
L
L
Bool
For P and B the eq functions are fairly
straightforward, but let's look at the implementation of eqB:
eqB eqa NilB NilB = True
eqB eqA NilB _ = False
eqB eqA _ NilB = False
eqB eqA (ConsB x xb) (ConsB y yb) = (eqa x y) (eqB (eqB eqa) xb xy)
Note that with the recursive call to eqB, we are checking for
the equality of xb and yb, which have the type
Bush (Bush ). Hence, the implementation of
eqB requires polymorphic recursion, and requires explicit
typing:
eqB :: (
Bool)
B
B
Bool
Finally, consider the implementation of eqG:
eqG eqf eqa (Branch x xg) (Branch y yg) = (eqa x y) (eqf (eqG eqf eqa) xg yg)
That is, given a way to check the equality of
structures and of
values, we can check the equality
of a G
datatype by comparing the two
values of type
with eqa and by comparing
the two structures of type
(G
) with eqf. At a minimum, we type eqG as follows:
eqG :: ((G
G
Bool)
(G
)
(G
)
Bool)
(
Bool)
G
G
Bool
However, for reasons that won't become apparent until a later talk, it
makes sense to type eqG as follows, using rank-2 polymorphism:
eqG :: (. (
Bool)
Bool)
(
Bool)
G
G
Bool
Some similarities among all of these functions: