A casual trip to the Monad, through Scalaz

We had a meetup reading 2nd chapter of Reactive Programming with Scala and Akka last Friday.

The first half of this chapter explains what is functional programming in Scala. And the latter, through one of the most popular Scala library called Scalaz, the important concepts in functional programming; Functors, Applicative Functors, and Monads.

In this blog post, I will explain about my shallow understanding of those three handsome guys.

Disclaimer: the below is not thorough nor correct definitions of those concepts at all. It simply is a starting point for understanding them.

Functors, Applicative Functors, and Monads, for the first step

If you don’t know very much about functors, applicative functional, and monads (like me as a Scala newbie), maybe a table below could help understand them.

Who are you? does what, mainly in which method
Functor maps a value A in some container F map[B](f: A => B): F[B]
Applicative applies a method A => B in some container F
to a value A in another container F
ap[A,B](f: => F[A => B]): F[B]
Monad flatMaps a value A in some container F bind[A, B](f: A => F[B]): F[B]

Here, the word container means kind of an abstraction of a way of holding value. Option, List and Future are good examples of them in Scala language.

type how it holds value
Option[T] holds a value of type T (Some(value)), or nothing (None)
List[T] holds multiple values of type T.
(that is, homogeneous collection of type T)
Future[T] holds some concurrent block that will eventually return
the value of type T, or Throwable as a failure result.

NOTE: Strictly speaking, container should actually be called a type class. See Wikipaedia for further explanations.

And Monads flatMap (or bind), this flattens the nested container as a result of mapping.

Anyway for better understandings let’s check out their implemtation in Scalaz’s source code with some examples.

Implementations & Examples

  • Functor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// From Scalaz, details omitted

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

object Functor {
def apply[F[_]](implicit F: Functor[F]): Functor[F] = F
}

class FunctorOps[F[_],A](val self: F[A])(implicit val F: Functor[F]) {
def map[B](f: A => B): F[B] = F.map(self)(f)
...
}

trait FunctorSyntax[F[_]] extends InvariantFunctorSyntax[F] {
implicit def ToFunctorOps[A](v: F[A]): FunctorOps[F, A] =
new FunctorOps[F,A](v)(FunctorSyntax.this.F)
def F: Functor[F]
}

// Examples

import scalaz._, Scalaz._

Functor[List].map(1 to 10) {_ + 1}
// List(2, ..., 11)

Functor[Option].map(Some(10)) {_ + 1}
// Some(11)
  • Applicative (Applicative extends Apply)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// From Scalaz, details omitted

trait Apply[F[_]] extends Functor[F] {
def ap[A,B](fa: => F[A])(f: => F[A => B]): F[B]
...
}

trait Applicative[F[_]] extends Apply[F] {
def point[A](a: => A): F[A]
def pure[A](a: => A): F[A] = point(a)
def map[A, B](fa: F[A])(f: A => B): F[B] = ap(fa)(point(f))
...
}

object Applicative {
def apply[F[_]](implicit F: Applicative[F]): Applicative[F] = F
}

class ApplicativeOps[F[_],A](val self: F[A])(implicit val F: Applicative[F]) {
...
}

trait ApplicativeSyntax[F[_]] extends ApplySyntax[F] {
implicit def ToApplicativeOps[A](v: F[A]): ApplicativeOps[F, A] =
new ApplicativeOps[F,A](v)(ApplicativeSyntax.this.F)
}

// Examples

import scalaz._, Scalaz._

List(1, 2, 4) <*> List({(_:Int) * 3})
// List(3, 6, 12)

List(1, 2, 4) <*> {(_:Int) * 3}.point[List]
// List(3, 6, 12)

// when you want to apply functions at a time
val values = List(1, 2, 4)
val funcs1 = List({(_:Int) * 3})
val funcs2 = List({(_:Int) + 3})

// verbose!
val resultUsingFlatMap: List[Int] =
funcs1.flatMap { func1 =>
funcs2.flatMap { func2 =>
values.map { value =>
(func1 andThen func2)(value)
}
}
}

// concise!
val resultUsingFor: List[Int] =
for {
value <- values
func1 <- funcs1
func2 <- funcs2
} yield (func1 andThen func2)(value)

// more concise!?
// <*> is an alias for ap
val resultUsingApplicative: List[Int] =
values <*> funcs1 <*> funcs2
  • Monad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// From Scalaz, details omitted

trait Bind[F[_]] extends Apply[F] {
def bind[A, B](fa: F[A])(f: A => F[B]): F[B]
def ap[A, B](fa: => F[A])(f: => F[A => B]): F[B]
}

trait Monad[F[_]] extends Applicative[F] with Bind[F] {
def ap[A, B](fa: => F[A])(f: => F[A => B]): F[B]
...
}

object Monad {
def apply[F[_]](implicit F: Monad[F]): Monad[F] = F
}

class MonadOps[F[_],A](val self: F[A])(implicit val F: Monad[F]) {
...
}

trait MonadSyntax[F[_]] extends ApplicativeSyntax[F] with BindSyntax[F] {
implicit def ToMonadOps[A](v: F[A]): MonadOps[F, A] =
new MonadOps[F,A](v)(MonadSyntax.this.F)
def F: Monad[F]
}

// Examples

import scalaz._, Scalaz._

val value = "126"
val map = Map(10 -> "ten", 42 -> "the answer")
val toIntOption: String => Option[Int] = value => try { value.toInt.some } catch { case e: NumberFormatException => None }
val toDivBy3Option: Int => Option[Int] = value => (value % 3 == 0) ? (value / 3).some | None

// verbose version
toIntOption(value).flatMap { intValue =>
toDivBy3Option(intValue).flatMap { divBy3Value =>
map.get(divBy3Value)
}
}

// for comprehension
for {
intValue <- toIntOption(value)
divBy3Value <- toDivBy3Option(intValue)
mappedValue <- map.get(divBy3Value)
} yield mappedValue

// with sexy operators
// >>= is an alias for bind
Monad[Option].point(value) >>= toIntOption >>= toDivBy3Option >>= map.get

But what are these XxxOps and XxxSyntax??? This is kind of what we call pimp my library pattern in Scala, to add methods on target class or trait without modifying it, using the power of implicit conversion.

Its basic structure in Scalaz can be simplified like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Original

trait OriginalOps(val self: Original) {
def additionalMethod = ...
}

trait Syntax {
implicit def ToOriginalOps(original: Original): OriginalOps =
new OriginalOps(original)
}

object Syntax extends Syntax

// usage
import Syntax._

val original = new Original
original.additionalMethod

By the way,

Is there any easy good way to write some fancy operators like "η", "⊛", or "∘", without simply copy-and-pasting them? Once in a while I feel like to indulge in using them with a bit of fear about Gestaltzerfall…

Other helpful resources

For those who want to dive more into functional programming…

Oneteam Inc. is hiring a Scala engineer for server-side development. Please visit HERE