Scala Lesson 34 – Monads | Dataplexa

Monads

In this lesson, you will learn about Monads in Scala. Monads are a core concept in functional programming and are widely used to manage data flow, side effects, optional values, and errors in a clean and predictable way.

Although the term “monad” sounds complex, the idea becomes simple once you see real examples and how Scala uses monads in everyday code.


What Is a Monad?

A monad is a design pattern that wraps a value and provides a standard way to:

  • Apply operations to the wrapped value
  • Chain multiple computations together
  • Handle absence, failure, or context safely

In Scala, monads are types that support the operations map and flatMap.


Why Monads Are Important

Monads help you avoid:

  • Null pointer exceptions
  • Deeply nested conditional logic
  • Unclear error handling

They allow you to write code that is expressive, composable, and safe.


Option as a Monad

Option is one of the most common monads in Scala. It represents a value that may or may not exist.

val maybeNumber: Option[Int] = Some(10)

Using map with Option:

val result = maybeNumber.map(_ * 2)
println(result)

If the value is None, the computation safely skips.


Chaining with flatMap

flatMap is used when the operation itself returns a monad.

def divide(a: Int, b: Int): Option[Int] =
  if (b == 0) None else Some(a / b)

val result =
  Some(20).flatMap(x => divide(x, 2))

println(result)

This prevents nested Options like Option[Option[Int]].


For-Comprehensions and Monads

Scala’s for-comprehensions are syntax sugar built on top of map and flatMap.

val result = for {
  a <- Some(10)
  b <- Some(5)
} yield a + b

println(result)

This code is easier to read and behaves the same as chained flatMaps.


Either as a Monad

Either represents a value that can be one of two types, usually used for error handling.

def parseInt(s: String): Either[String, Int] =
  try {
    Right(s.toInt)
  } catch {
    case _: NumberFormatException => Left("Invalid number")
  }

Using map with Either:

val result = parseInt("42").map(_ * 2)
println(result)

Try as a Monad

Try is another monad used to capture exceptions safely.

import scala.util.Try

val result = Try(10 / 2).map(_ * 3)
println(result)

Failures are automatically wrapped as Failure.


Common Monad Pattern

Most monads follow this pattern:

  • Wrap a value in a context
  • Apply transformations safely
  • Chain computations without breaking flow

Option, Either, Try, Future, and collections are all monads in Scala.


When to Use Monads

Use monads when:

  • Handling optional or missing values
  • Managing errors without exceptions
  • Chaining dependent computations
  • Working with async or collections

📝 Practice Exercises


Exercise 1

Create an Option and use map to transform its value.

Exercise 2

Write a function that returns Either and handle errors safely.

Exercise 3

Rewrite a flatMap chain using a for-comprehension.


✅ Practice Answers


Answer 1

val opt = Some(5)
opt.map(_ + 10)

Answer 2

def safeDivide(a: Int, b: Int): Either[String, Int] =
  if (b == 0) Left("Division by zero") else Right(a / b)

Answer 3

val result = for {
  x <- Some(10)
  y <- Some(2)
} yield x / y

What’s Next?

In the next lesson, you will learn about Either & Try in detail and see how Scala handles errors in a functional and expressive way.