Home > Software design >  Is Control.Monad.Reader.withReader actually Data.Functor.Contravariant.contramap?
Is Control.Monad.Reader.withReader actually Data.Functor.Contravariant.contramap?

Time:11-04

I'm working trough the book Haskell in depth and I noticed following code example:

withReader :: (r' -> r) -> Reader r a -> Reader r' a

This looks like contramap. What the relationship between Control.Monad.Reader and Data.Functor.Contravariant?

CodePudding user response:

Reader's type parameters aren't in the right order for that to be contramap for it. A Contravariant functor always needs to be contravariant in its last type parameter, but Reader is contravariant in its first type parameter. But you can do this:

newtype FlippedReader a r = FlippedReader (Reader r a)

instance Contravariant (FlippedReader a) where
    contramap f (FlippedReader x) = FlippedReader (withReader f x)

Reader is also almost a Profunctor, with lmap = withReader and rmap = fmap, but that doesn't quite work since Reader r a is really a type synonym for ReaderT r Identity a (although you could use another newtype wrapper to make it work like I did above). And (->) actually is a Profunctor with equivalent behavior, and it's isomorphic to Reader.

  • Related