Last active
May 20, 2024 15:41
-
-
Save sshark/6a169bedfa97718dd72eb0738fbb046f to your computer and use it in GitHub Desktop.
An exercise to implement Monad in Scala 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Functor[F[_]]: | |
def map[A, B](fa: F[A])(f: A => B): F[B] | |
trait Monad[F[_]] extends Functor[F]: | |
def unit[A](a: A): F[A] | |
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] | |
def map[A, B](fa: F[A])(f: A => B): F[B] = flatMap(fa)(x => unit(f(x))) | |
object Monad: | |
def apply[F[_]](using ev: Monad[F]): Monad[F] = ev | |
object MonadSyntax: | |
extension[F[_], A](fa: F[A])(using ev: Monad[F]) | |
def flatMap[B](f: A => F[B]): F[B] = ev.flatMap(fa)(f) | |
def map[B](f: A => B): F[B] = ev.map(fa)(f) | |
trait MyBox[+A] | |
case class FilledBox[A](x: A) extends MyBox[A] | |
case object EmptyBox extends MyBox[Nothing] | |
object MyBox: | |
def apply[A](a: A): MyBox[A] = FilledBox(a) | |
def empty: MyBox[Nothing] = EmptyBox | |
given Monad[MyBox] with | |
override def unit[A](a: A) = FilledBox(a) | |
override def flatMap[A, B](fa: MyBox[A])(f: A => MyBox[B]): MyBox[B] = | |
fa match | |
case FilledBox(x) => f(x) | |
case EmptyBox => EmptyBox | |
import MonadSyntax.* | |
def showMyBox[A](box: MyBox[A]): String = | |
box match | |
case FilledBox(x) => s"The result is $x" | |
case _ => "Nothing there" | |
val result = for { | |
a <- MyBox(1) | |
b <- MyBox(2) | |
} yield a + b | |
println(showMyBox(result)) | |
val empty = for { | |
a <- MyBox(1) | |
_ <- MyBox.empty | |
} yield a | |
println(showMyBox(empty)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment