The Contravariant
family of typeclasses represents standard and fundamental abstractions in the Haskell ecosystem:
class Contravariant f where
contramap :: (a -> b) -> f b -> f a
class Contravariant f => Divisible f where
conquer :: f a
divide :: (a -> (b, c)) -> f b -> f c -> f a
class Divisible f => Decidable f where
lose :: (a -> Void) -> f a
choose :: (a -> Either b c) -> f b -> f c -> f a
However, it's not that easy to understand the concepts behind these typeclasses. I think it would help to understand these typeclasses better if you could see some counterexamples for them. So, in the spirit of Good examples of Not a Functor/Functor/Applicative/Monad?, I'm looking for contrasting examples of data types which satisfy the following requirements:
- A type constructor which is not a
Contravariant
? - A type constructor which is a
Contravariant
, but notDivisible
? - A type constructor which is a
Divisible
, but is not aDecidable
? - A type constructor which is a
Decidable
?
Contravariant
, but this also not the most interesting part of the question :) – Eponymousnewtype C a = C (a -> Int)
is contravariant. – FrumentyDivisible
had a superclass withdivide
but notconquer
, dual toApply
. – DinericComonad
here is that it is not a subclass ofDivisible
. Its relationship withMonad
is not the same as the one betweenDivisible
andAlternative
. (In a cursory way: (1a) AMonad
is a monad in Hask; (1b) AComonad
is a monad in the dual category Hask^op, which we encode within Hask by flipping some arrows; (2a) AnApplicative
is a monoidal endofunctor in Hask; (2b) ADivisible
is a monoidal functor from Hask^op to Hask, which we encode within Hask by flipping some arrows, but not quite in the same way.) – Lousewort