Let's first consider specializing reduce to a simple
type, like D or C. In this case, then
reduce will have the following type:
reduce<D> ::
(
)
(D
)
In order to specialize, we need a way of relating the datatype
D to the mini constructor language. To this end, we
introduce a new datatype D that is isomorphic to
D, but only uses the constructors of the mini constructor
language:
data D
= 1 :+: (1 :+: (
))
We further introduce two functions that witness the isomorphism:
fromD :: D
D
fromD Sun = Inl Unit
fromD Mon = Inr (Inl Unit)
toD :: D
D
fromD (Inl Unit) = Sun
fromD (Inr (Inl Unit)) = Mon
We specialize reduce to D by simply
unrolling the definition:
D
:
reduce<D>
= red<D
>
where
red<D>
= red<1 :+: (1 :+: ( ) )>
= red<:+:> red<1> (red<1 :+: ( )>)
= red<:+:> red<1> (red<:+:> red<1> ( ))
Now, we have implementations of red<:+:> and red<1>
given in the definition of reduce, which can be used here to
complete the definition of reduce<D
>.
How do we specialize reduce to D? The simplest way
is to use reduce<D> along with the function
fromD:
reduce<D>
= (reduce<D
>
)
fromD
We might well wonder ``What is the use of reduce<D>?'' It is
not hard to see that reduce<D>
returns
for all values
of type D. We might think then that
reduce is not a useful function, but the usefulness of
reduce becomes apparent when it is specialized to type
constructors like L and B.