Without justification, we assert that the type of reduce<L>
is the following:
reduce<L> ::
(
)
(
. (
)
L
)
As with reduce<D>, we introduce a new datatype isomorphic to L:
data L
= 1 :+: (
:*: (L
))
fromL :: L L
fromL Nil = Inl Unit
fromL (Cons x xl) = Inr (x :*: xl)
toL :: L
L
toL (Inl Unit) = Nil
toL (Inr (x :*: xl)) = Cons x xl
Note that L is defined in terms of L.
L
is isomorphic to ``one unrolling'' of L,
which is sufficient for our purposes.
We proceed with specialization of reduce to
L by unrolling the definition. The ``new'' argument
in the type of reduce<L> above corresponds to ``what to do''
when the unrolling encounters the polymorphic type variable
:
reduce<L>
ra = (reduce<L
>
ra)
fromL
reduce<L>
ra = red<L
>
where
red<L>
= red<1 :+: ( :*: (L
))>
= red<:+:> red<1> red< :*: (L
)>
= red<:+:> red<1> (red<:*:> red<> red<L
>)
At this point, we can use ra as the interpretation of red<>
= red<:+:> red<1> (red<:*:> ra red<L >)
Furthermore, we interpret the type application in L
as the value application red<L> red<
>
= red<:+:> red<1> (red<:*:> ra (red<L> red<>))
= red<:+:> red<1> (red<:*:> ra (red<L> ra>))
For reasons that aren't entirely apparent from the ad hoc approach
we've taken to defining polytypic functions and to specializing
polytypic functions, the appropriate interpretation of red<L>
is reduce<L>
>. Hopefully, this at least makes
intuitive sense.
= red<:+:> red<1> (red<:*:> ra ((reduce<L>
) ra>))
Similarly, we attack the specialization of reduce to B:
reduce<B> ::
(
)
(
. (
)
B
)
data B
= 1 :+: (
:*: (B (B
)))
fromB :: B B
fromB NilB = Inl Unit
fromB (ConsB x xb) = Inr (x :*: xb)
toB :: B
B
toB (Inl Unit) = NilB
toB (Inr (x :*: xb)) = ConsB x xb
reduce<B>
ra = (reduce<B
>
ra)
fromB
reduce<B>
ra = red<B
>
where
red<B>
= red<1 :+: ( :*: (B (B
)))>
= red<:+:> red<1> red< :*: (B (B
))>
= red<:+:> red<1> (red<:*:> red<> red<B (B
)>)
= red<:+:> red<1> (red<:*:> red<> (red<B> red<B
>))
= red<:+:> red<1> (red<:*:> red<> (red<B> (red<B> red<
>)))
= red<:+:> red<1> (red<:*:> ra (red<B> (red<B> ra)))
= red<:+:> red<1> (red<:*:> ra ((reduce<B>
) ((reduce<B>
) ra)))
Finally, consider the following instantiations of reduce:
fsize<> ::
Int
fsize<> = reduce<
> 0 (+) (const 1)
fall<> :: (
Bool)
Bool
fall<> p = reduce<
> True (
) p
fflatten<> ::
L
fflatten<> = reduce<
> Nil (++) wrap
where wrap x = Cons x Nil