Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Functor and Monad differences

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

like image 743
dimitrisli Avatar asked Dec 10 '11 23:12

dimitrisli


People also ask

What is the difference between functor and monad?

A functor takes a pure function (and a functorial value) whereas a monad takes a Kleisli arrow, i.e. a function that returns a monad (and a monadic value). Hence you can chain two monads and the second monad can depend on the result of the previous one.

Could you comfortably explain the difference between a monad and an applicative functor?

Functors apply a function to a wrapped value: Applicatives apply a wrapped function to a wrapped value: Monads apply a function that returns a wrapped value to a wrapped value. Monads have a function >>= (pronounced "bind") to do this.

What is functor in Scala?

A Functor is a ubiquitous type class involving types that have one "hole", i.e. types which have the shape F[*] , such as Option , List and Future . (This is in contrast to a type like Int which has no hole, or Tuple2 which has two holes ( Tuple2[*,*] )).

What is monad in Scala?

In Scala, Monads is a construction which performs successive calculations. It is an object which covers the other object. It is worth noting that here, the output of an operation at some step is an input to another computations, which is a parent to the recent step of the program stated.


2 Answers

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.

like image 198
huynhjl Avatar answered Oct 02 '22 18:10

huynhjl


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.

like image 33
oxbow_lakes Avatar answered Oct 02 '22 18:10

oxbow_lakes