Scala Functor and Monad differences

Scala itself really does not emphasize the Functor and Monad terms that much. I guess using map is the functor side, using flatMap is the Monad side.

For me looking and playing around with scalaz has been so far the best avenue to get a sense of those functional concepts in the scala context (versus the haskell context). Two years ago when I started scala, the scalaz code was gibberish to me, then a few months ago I started looking again and I realized that it's really a clean implementation of that particular style of functional programming.

For instance the Monad implementation shows that a monad is a pointed functor because it extends the Pointed trait (as well as the Applicative trait). I invite you to go look at the code. It has linking in the source itself and it's really easy to follow the links.

So functors are more general. Monads provide additional features. To get a sense of what you can do when you have a functor or when you have a monad, you can look at MA

You'll see utility methods that need an implicit functor (in particular applicative functors) such as sequence and sometime methods that needs a full monad such as replicateM.


Taking scalaz as the reference point, a type F[_] (that is, a type F which is parameterized by some single type) is a functor if a function can be lifted into it. What does this mean:

class Function1W[A, B](self: A => B) { 
  def lift[F[_]: Functor]: F[A] => F[B]
}

That is, if I have a function A => B, a functor F[_], then I now have a function F[A] => F[B]. This is really just the reverse-way of looking at scala's map method, which (ignoring the CanBuildFrom stuff) is basically:

F[A] => (A => B) => F[B]

If I have a List of Strings, a function from String to Int, then I can obviously produce a List of Ints. This goes for Option, Stream etc. They are all functors

What I find interesting about this is that you might immediately jump to the (incorrect) conclusion that a Functor is a "container" of As. This is an unnecesssary restriction. For example, think about a function X => A. If I have a function X => A and a function A => B then clearly, by composition, I have a function X => B. But now, look at it this way:

type F[Y] = X => Y //F is fixed in X

(X => A) andThen (A => B) is   X => B

  F[A]            A => B       F[B]

So the type X => A for some fixed X is also a functor. In scalaz, functor is designed as a trait as follows:

trait Functor[F[_]] { def fmap[A, B](fa: F[A], f: A => B): F[B] }

hence the Function1.lift method above is implemented

def lift[F[_]: Functor]: F[A] => F[B] 
  = (f: F[A]) => implicitly[Functor[F]].fmap(f, self)

A couple of functor instances:

implicit val OptionFunctor = new Functor[Option] {
  def fmap[A, B](fa: Option[A], f: A => B) = fa map f
}

implicit def Functor1Functor[X] = new Functor[({type l[a]=X => a})#l] {
  def fmap[A, B](fa: X => B, f: A => B) = f compose fa
}

In scalaz, a monad is designed like this:

trait Monad[M[_]] {
  def pure[A](a: A): M[A] //given a value, you can lift it into the monad
  def bind[A, B](ma: M[A], f: A => B): M[B]
}

It is not particularly obvious what the usefulness of this might be. It turns out that the answer is "very". I found Daniel Spiewak's Monads are not Metaphors extremely clear in describing why this might be and also Tony Morris's stuff on configuration via the reader monad, a good practical example of what might be meant by writing your program inside a monad.