Given a trait `Option` and two implementations:

``````sealed trait Option[A] {

def map[B](f: A => B): Option[B] = ???

def flatMap[B](f: A => Option[B]): Option[B] = ???

override def toString(): String =
this match {
case Some(a) => "Some(" + a + ")"
case None()  => "None()"
}
}

case class Some[A](a: A) extends Option[A]
case class None[A]() extends Option[A]``````

Implement `map` and `flatMap` so that we can use `Option` in a `for`-comprehension:

``````def quotient(divisor: Int)(dividend: Int): Int =
dividend / divisor

def remainder(divisor: Int)(dividend: Int): Option[Int] =
(dividend % divisor) match {
case 0 => None()
case r => Some(r)
}

val x3 =
for {
x <- Some(42)
q  = quotient(2)(x)
r <- remainder(4)(x)
} yield (x,q,r)

println(x3) // Some((42,21,2))``````

Solution

Here is one possible solution.
``````sealed trait Option[A] {

def map[B](f: A => B): Option[B] =
this match {
case Some(a) => Some(f(a))
case None()  => None()
}

def flatMap[B](f: A => Option[B]): Option[B] =
this match {
case Some(a) => f(a)
case None()  => None()
}

override def toString(): String =
this match {
case Some(a) => "Some(" + a + ")"
case None()  => "None()"
}
}

case class Some[A](a: A) extends Option[A]
case class None[A]() extends Option[A]``````

Demo

This file is literate Scala, and can be run using Codedown:

``````\$ curl https://earldouglas.com/posts/exercises/scala-option.md |
codedown scala |
xargs -0 scala -nc -e
Some((42,21,2))``````