Search code examples
haskellcategory-theory

Showing that `newtype T a = T (a -> Int)` is a Type Constructor that is Not a Functor


It's been claimed that newtype T a = T (a -> Int) is a type constructor that is not a functor (but is a contravariant functor). How so? Or what is the contravariant functor (whence I assume it will be obvious why this can't be made a normal functor)?


Solution

  • Given

    newtype T a = T (a -> Int)
    

    let's try to build the Contravariant instance for this datatype.

    Here's the typeclass in question:

    class Contravariant f where
      contramap :: (a -> b) -> f b -> f a
    

    Basically, contramap is akin to fmap, but instead of lifting a function a -> b to f a -> f b, it lifts it to f b -> f a.

    Let's begin writing the instance...

    instance Contravariant T where
      contramap g (T f) = ?
    

    Before we fill in the ?, let's think about what the types of g and f are:

    g :: a -> b
    f :: b -> Int
    

    And for clarity, we might as well mention that

    f a ~ T (a -> Int)
    f b ~ T (b -> Int)
    

    So we can fill in the ? as follows:

    instance Contravariant T where
      contramap g (T f) = T (f . g)
    

    To be super pedantic, you might rename g as aToB, and f as bToInt.

    instance Contravariant T where
      contramap aToB (T bToInt) = T (bToInt . aToB)
    

    The reason you can write a Contravariant instance for T a boils down to the fact that a is in contravariant position in T (a -> Int). The best way to convince yourself that T a isn't a Functor is to try (and fail) to write the Functor instance yourself.