Given:
class Contravariant (f :: * -> *) where
contramap :: (a -> b) -> f b -> f a
The following code is rejected. I'm expecting to get String -> Bool
(a predicate) as a result of contra-mapping Int -> Bool
over String -> Int
. I feel stupid as I must be making some wrong assumptions. Please help me in understanding the error message. Why is the second argument expected to be different than the one I think I need?
Prelude Control.Lens> contramap length (>0) "Hello"
<interactive>:25:19: error:
• Couldn't match type ‘Bool’ with ‘Int’
Expected type: [Char] -> Int
Actual type: [Char] -> Bool
• In the second argument of ‘contramap’, namely ‘(> 0)’
In the expression: contramap length (> 0) "Hello"
In an equation for ‘it’: it = contramap length (> 0) "Hello"
Contravariant only works on the last argument of a type constructor. You might want Profunctor
, which denotes type constructors that are contravariant in the second to last argument and covariant (like a regular Functor) in the last one.
<Gurkenglas> > lmap length (>0) "hello"
<lambdabot> True