Search code examples
haskellcontravariance

How to contramap over functions?


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"

Solution

  • 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