Safe Haskell | None |
---|---|
Language | Haskell2010 |
Decidable
class Divisible f => Decidable (f :: * -> *) where #
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 dicussion for Divisible
, an example was demonstrated with Serializer
s,
that turn a
s into ByteString
s. 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 String
s or Int
s:
data Identifier = StringId String | IntId Int
We know we have serializers for String
s and Int
s, 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
Acts as identity to choose
.
Instances
contramany :: Decidable f => f a -> f [a] #