Scala Functor and Monad differences

ScalaFunctional Programming

Scala Problem Overview


Can please someone explain the differences between Functor and Monad in the Scala context?

Scala Solutions


Solution 1 - Scala

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.

Solution 2 - Scala

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.

Solution 3 - Scala

A while ago I wrote about that: http://gabrielsw.blogspot.com/2011/08/functors-applicative-functors-and.html (I'm no expert though)

The first thing to understand is the type ' T[X] ' : It's a kind of "context" (is useful to encode things in types and with this you're "composing" them) But see the other answers :)

Ok, now you have your types inside a context, say M[A] (A "inside" M), and you have a plain function f:A=>B ... you can't just go ahead and apply it, because the function expects A and you have M[A]. You need some way to "unpack" the content of M, apply the function and "pack" it again. If you have "intimate" knowledge of the internals of M you can do it, if you generalize it in a trait you end with

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

And that's exactly what a functor is. It transforms a T[A] into a T[B] by applying the function f.

A Monad is a mythical creature with elusive understanding and multiple metaphors, but I found it pretty easy to understand once you get the applicative functor:

Functor allow us to apply functions to things in a context. But what if the functions we want to apply are already in a context? (And is pretty easy to end in that situation if you have functions that take more than one parameter).

Now we need something like a Functor but that also takes functions already in the context and applies them to elements in the context. And that's what the applicative functor is. Here is the signature:

trait Applicative[T[_]] extends Functor[T]{
  def pure[A](a:A):T[A]
  def <*>[A,B](tf:T[A=>B])(ta:T[A]):T[B]
}

So far so good. Now comes the monads: what if now you have a function that puts things in the context? It's signature will be g:X=>M[X] ... you can't use a functor because it expects X=>Y so we'll end with M[M[X]], you can't use the applicative functor because is expecting the function already in the context M[X=>Y] .

So we use a monad, that takes a function X=>M[X] and something already in the context M[A] and applies the function to what's inside the context, packing the result in only one context. The signature is:

trait Monad[M[_]] extends Applicative[M]{
  def >>=[A,B](ma:M[A])(f:A=>M[B]):M[B]
}

It can be pretty abstract, but if you think on how to work with "Option" it shows you how to compose functions X=>Option[X]

EDIT: Forgot the important thing to tie it: the >>= symbol is called bind and is flatMap in Scala. (Also, as a side note, there are some laws that functors, applicatives, and monads have to follow to work properly).

Solution 4 - Scala

The best article laying out in details those two notions is "The Essence of the Iterator Pattern " from Eric Torreborre's Blog.

Functor

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

> - One way of interpreting a Functor is to describe it as a computation of values of type A.
For example:

  • List[A] is a computation returning several values of type A (non-deterministic computation),
  • Option[A] is for computations that you may or may not have,
  • Future[A] is a computation of a value of type A that you will get later, and so on.
  • Another way of picturing it is as some kind of "container" for values of type A.

It is the basic layer from which you define:

  • PointedFunctor (to create a value of type F[A]) and
  • Applic (to provide a method applic, being a computed value inside the container F (F[A => B]), to apply to a value F[A]), Applicative Functor (aggregation of an Applic and a PointedFunctor).

All three elements are used to define a Monad.

Solution 5 - Scala

I think this great blog post will help you first for monad. http://blog.enfranchisedmind.com/2007/08/a-monad-tutorial-for-ocaml/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondimitrisliView Question on Stackoverflow
Solution 1 - ScalahuynhjlView Answer on Stackoverflow
Solution 2 - Scalaoxbow_lakesView Answer on Stackoverflow
Solution 3 - ScalaGClaramuntView Answer on Stackoverflow
Solution 4 - ScalaVonCView Answer on Stackoverflow
Solution 5 - ScalaJackson TaleView Answer on Stackoverflow