I read many articles about contramap and find https://hackage.haskell.org/package/contravariant-1.4.1/docs/Data-Functor-Contravariant.html#g:3 is the best.
Anyway I found, how to use for example:
*Lib Data.Functor.Contravariant> a = Predicate (\x -> x > 20)
*Lib Data.Functor.Contravariant> :t contramap
contramap :: Contravariant f => (a -> b) -> f b -> f a
*Lib Data.Functor.Contravariant> :t contramap (\x -> x * 2)
contramap (\x -> x * 2) :: (Num b, Contravariant f) => f b -> f b
*Lib Data.Functor.Contravariant> :t contramap (\x -> x * 2) a
contramap (\x -> x * 2) a :: (Ord b, Num b) => Predicate b
*Lib Data.Functor.Contravariant> x = contramap (\x -> x * 2) a
*Lib Data.Functor.Contravariant> getPredicate x 45
True
But could not figure out, where it can be useful.
On the website, that I posted above, it says:
Whereas in Haskell, one can think of a Functor as containing or producing values, a contravariant functor is a functor that can be thought of as consuming values.
Look at the definition of the functor:
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
It consumes the value of type a
and it produces the value of type b
. On contramap
it consumes the value.
class Contravariant (f :: * -> *) where
contramap :: (a -> b) -> f b -> f a
Which variable type does it consume a
or b
?
Also a question from https://www.fpcomplete.com/blog/2016/11/covariance-contravariance about POSITIVE AND NEGATIVE POSITION. On the website it says:
- Positive position: the type variable is the result/output/range/codomain of the function
- Negative position: the type variable is the argument/input/domain of the function
Looking at contramap type definition:
contramap :: (a -> b) -> f b -> f a
Which type variable does the author point to?