Last active
December 17, 2015 12:39
-
-
Save xuwei-k/5611368 to your computer and use it in GitHub Desktop.
Monad without map, flatMap, yield
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
scalaVersion := "2.11.6" |
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
sealed trait Maybe[+A] | |
case class Just[+A](a: A) extends Maybe[A] | |
case object Not extends Maybe[Nothing] | |
sealed trait ConsList[+A]{ | |
final def ::[AA >: A](h: AA): ConsList[AA] = Cons(h, this) | |
final def :::[AA >: A](h: ConsList[AA]): ConsList[AA] = { | |
def loop(other: ConsList[AA]): ConsList[AA] = other match{ | |
case Cons(head, tail) => head :: loop(tail) | |
case NIL => this | |
} | |
loop(h) | |
} | |
} | |
final case class Cons[+A](private val head: A, private val tail: ConsList[A]) extends ConsList[A] | |
final case object NIL extends ConsList[Nothing] | |
trait Monad[F[_]]{ | |
def point[A](a: A): F[A] | |
def bind[A, B](fa: F[A])(f: A => F[B]): F[B] | |
} | |
object Main extends App{ | |
implicit val maybeMonad: Monad[Maybe] = new Monad[Maybe]{ | |
def bind[A, B](fa: Maybe[A])(f: A => Maybe[B]) = fa match{ | |
case Just(a) => f(a) | |
case Not => Not | |
} | |
def point[A](a: A) = Just(a) | |
} | |
implicit val listMonad: Monad[ConsList] = new Monad[ConsList]{ | |
def bind[A, B](fa: ConsList[A])(f: A => ConsList[B]) = fa match{ | |
case Cons(head, tail) => f(head) ::: bind(tail)(f) | |
case NIL => NIL | |
} | |
def point[A](a: A) = Cons(a, NIL) | |
} | |
implicit class MonadSyntax1[A](val a: A) extends AnyVal{ | |
def point[F[_]: Monad]: F[A] = implicitly[Monad[F]].point(a) | |
} | |
implicit class MonadSyntax2[A, F[_]: Monad](val fa: F[A]){ | |
def foreach[B](f: A => F[B]) = implicitly[Monad[F]].bind(fa)(f) | |
} | |
def not[A]: Maybe[A] = Not | |
val r1 = for{ | |
a <- 1.point[Maybe] | |
b <- 2.point[Maybe] | |
c <- 3.point[Maybe] | |
} (a, b, c).point[Maybe] | |
assert(r1 == Just((1,2,3))) | |
val r2 = for{ | |
a <- not[Int] | |
b <- 2.point[Maybe] | |
} (a, b).point[Maybe] | |
assert(r2 == Not) | |
val r3 = for{ | |
a <- 1 :: 2 :: NIL | |
b <- 3 :: 4 :: NIL | |
} (a, b).point[ConsList] | |
assert(r3 == (1,3) :: (1,4) :: (2,3) :: (2,4) :: NIL) | |
val r4 = for{ | |
a <- 1 :: 2 :: NIL | |
b <- NIL: ConsList[Int] | |
c <- 3 :: 4 :: NIL | |
} (a, b, c).point[ConsList] | |
assert(r4 == NIL) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment