| Let me present this intuition I've developed. • You have a producer of Cs, then you can turn it into a producer of Ds by post-processing its output with a function g: C → D. • You have a consumer of Bs, then you can turn it into a consumer of As by pre-processing its input with a function f: A → B. • You have something that consumes Bs and produces Cs, then you can turn it into something that consumes As and produces Ds using two functions f: A → B and g: C → D. With pictures: http://mez.cl/prodcons.png If you understand that, you understand functors: • producer = (covariant) functor; • consumer = contravariant functor; • producer-consumer = invariant functor; • post-processing = map; • pre-process = contramap; • pre- and post-processing = xmap (in Scala), invmap (in Haskell); • defining how the pre- and post-processing works for a given producer or consumer = declaring a typeclass instance. It doesn't mean that "a functor is a producer", but the mechanics are the same. |