---
# System prepended metadata

title: Untitled

---

Implement a minimal `Option` that has `map` and `flatMap`.
```scala
import scala.{Option => _}
// implement here

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

object Functor {
    
    implicit val optionFunctor = new Functor[Option]{
        override def map[A,B](fa: F[A])(func: A => B): F[B]
    }
}

sealed trait Option[+A] {
    
    
    def map[B](func: A => B): Option[B] = {
        this match {
            case Some(a) => Some(func(a))
            case None    => None
        }
        fold(None)(a => Some(func(a)))
        
    }
    def flatMap[B](func: A => Option[B]): Option[B] = {
        this match {
            case Some(a) => func(a))
            case None    => None
        }
    }
    
    def fold[B](isEmpty: => B)(func: A => B): B = {
        this match {
            case Some(a) => func(a)
            case None    => isEmpty
        }
    }
}

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

def primeNr(nr: Int): Int = ??? // Computation

val foo: Option[Int] = Some(1)

lazy val empty = primeNr(Int.MaxValue)

foo.fold(empty)(_ + 1) // 

val bar: Option[Int] = None: Option[Nothing]
Option[Nothing] <: Option[Int]

foo.map(foo)(_ + 1)

foo.map(_ + 1)
bar.flatMap(Some(_ + 2))

// AnotherFile.scala
case class SNone[A](a: A) extends Option[A] // Should not be allowed
