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
Actually, you're looking for the boring old covariant Functor instance.
> fmap (>0) length "Hello"
True
At an even higher level, you may be looking for the null function. For many types, length will traverse the entire data structure you pass to it, whereas null generally will not.
Here is a short explanation of the error message, as well. First:
contramap length :: (Contravariant f, Foldable t) => f Int -> f (t a)
(>0) :: (Num a, Ord a) => (->) a Bool
I have aligned things in what I hope is a suggestive way. In order to apply contramap length to (>0), we would need to set f ~ (->) a and Int ~ Bool. The second is clearly impossible, so the compiler complains. (N.B. The first equation is only subtly impossible; even if you supplied a function which returned an Int you'd have a problem, but the compiler doesn't notice yet because the obvious problem with the second equation trumps it. Namely: there is no Contravariant instance for (->) a, and can't be!)
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