I would like understand, why for example, the Maybe type is a covariant functor?
What does covariant mean?
Please provide an example to clarify.
A covariant functor is just the normal Functor class:
class Functor f where
fmap :: (a -> b) -> f a -> f b
For instance, Maybe (as you noted):
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
However, there is another type of functor: contravariant functors. These are defined as follows:
class Contravariant f where
contramap :: (a -> b) -> f b -> f a
Note that compared to fmap, contramap has reversed the order of b and a:
fmap :: Functor f => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a
-- ^ ^
-- look!
Now, does this crazy Contravariant class even have any instances? Well, yes. For example, here's the definition of a Predicate:
newtype Predicate x = Predicate { decide :: x -> Bool }
In other words, a Predicate x is a function which calculates a condition on an x. We can specialise contramap to Predicates:
contramap :: (a -> b) -> Predicate b -> Predicate a
Which is equivalent to:
contramap :: (a -> b) -> (b -> Bool) -> (a -> Bool)
Basically, given a Predicate on bs, and a mapping from as to bs, you can contramap to get a Predicate on as. (I'll leave the implementation as an exercise.) Here's an example (untested):
hasMultChars :: Predicate String
hasMultChars = Predicate $ \x -> length x > 1
showInt :: Int -> String
showInt = show
intHasMultChars :: Predicate Int
intHasMultChars = contramap showInt hasMultChars
As it turns out, contravariant functors are a lot less common - and so a lot less useful - than normal covariant functors. So in practise, we leave out the 'covariant', since it doesn't add anything in most cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With