A
Decidable contravariant functor is the contravariant analogue
of
Alternative.
Noting the superclass constraint that
f must also be
Divisible, a
Decidable functor has the ability to "fan
out" input, under the intuition that contravariant functors consume
input.
In the discussion for
Divisible, an example was demonstrated
with
Serializers, that turn
as into
ByteStrings.
Divisible allowed us to serialize the
product of multiple values by concatenation. By making our
Serializer also
Decidable- we now have the ability
to serialize the
sum of multiple values - for example different
constructors in an ADT.
Consider serializing arbitrary identifiers that can be either
Strings or
Ints:
data Identifier = StringId String | IntId Int
We know we have serializers for
Strings and
Ints,
but how do we combine them into a
Serializer for
Identifier? Essentially, our
Serializer needs to
scrutinise the incoming value and choose how to serialize it:
identifier :: Serializer Identifier
identifier = Serializer $ \identifier ->
case identifier of
StringId s -> runSerializer string s
IntId i -> runSerializer int i
It is exactly this notion of choice that
Decidable encodes.
Hence if we add an instance of
Decidable for
Serializer...
instance Decidable Serializer where
lose f = Serializer $ \a -> absurd (f a)
choose split l r = Serializer $ \a ->
either (runSerializer l) (runSerializer r) (split a)
Then our
identifier Serializer is
identifier :: Serializer Identifier
identifier = choose toEither string int where
toEither (StringId s) = Left s
toEither (IntId i) = Right i