Jaskell Typeclasses - MarchLiu/jaskell-core GitHub Wiki

Jaskell for Scala2 implement typeclasses by implicit.

Define a Monad Trait

trait Monad[M[_]] {
  def pure[A](element: A): M[A]

  def fmap[A, B](m: M[A], f: A => B): M[B]

  def flatMap[A, B](m: M[A], f: A => M[B]): M[B]

  def liftA2[A, B, C](f: (A, B) => C): (Monad.MonadOps[A, M], Monad.MonadOps[B, M]) => M[C] = { (ma, mb) =>
    for {
      a <- ma
      b <- mb
    } yield f(a, b)
  }

}

Declare Monad.apply

object Monad {
  def apply[M[_]](implicit instance: Monad[M]): Monad[M] = instance
  def apply[M[_]](implicit creator: () => Monad[M]): Monad[M] = creator.apply()
...
}

Declare implicit toMonad

object Monad {
...
  implicit def toMonad[A, M[_]](target: M[A])(implicit I: Monad[M]): MonadOps[A, M] =
    new MonadOps[A, M]() {
      override def self: M[A] = target
    }

  implicit def toMonad(implicit ec: ExecutionContext): Monad[Future] = new Monad[Future] {
    override def pure[A](element: A): Future[A] = Future.successful(element)

    override def fmap[A, B](m: Future[A], f: A => B): Future[B] = m.map(f)

    override def flatMap[A, B](m: Future[A], f: A => Future[B]): Future[B] = m.flatMap(f)
...
  }

Define Ops class

  abstract class MonadOps[A, M[_]](implicit I: Monad[M]) {
    def self: M[A]


    def map[B](f: A => B): M[B] = I.fmap(self, f)

    def <:>[B](f: A => B): M[B] = I.fmap(self, f)

    def flatMap[B](f: A => M[B]): M[B] = I.flatMap(self, f)

    def liftA2[B, C](f: (A, B) => C): (M[B]) => M[C] = m => I.liftA2(f)(self, m)

    def <*>[B](f: A => B): M[A] => M[B] = ma => I.fmap(ma, f)

    def *>[B](mb: M[B]): M[B] = for {
      _ <- self
      re <- mb
    } yield re

    def <*[_](mb: M[_]): M[A] = for {
      re <- self
      _ <- mb
    } yield re

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

    def >>[B](m: M[B]): M[B] = for {
      _ <- self
      re <- m
    } yield re

  }

Define Instances

These instances are not part of Parsec Monad, we just create them for other usages.

  implicit val listMonad: Monad[List] = new Monad[List] {
    override def pure[A](element: A): List[A] = List(element)

    override def fmap[A, B](m: List[A], f: A => B): List[B] = m.map(f)

    override def flatMap[A, B](m: List[A], f: A => List[B]): List[B] = m.flatMap(f)
  }


  implicit val seqMonad: Monad[Seq] = new Monad[Seq] {
    override def pure[A](element: A): Seq[A] = Seq(element)

    override def fmap[A, B](m: Seq[A], f: A => B): Seq[B] = m.map(f)

    override def flatMap[A, B](m: Seq[A], f: A => Seq[B]): Seq[B] = m.flatMap(f)
  }

  implicit val tryMonad: Monad[Try] = new Monad[Try] {
    override def pure[A](element: A): Try[A] = Success(element)

    override def fmap[A, B](m: Try[A], f: A => B): Try[B] = m.map(f)

    override def flatMap[A, B](m: Try[A], f: A => Try[B]): Try[B] = m.flatMap(f)
  }

Parsec Monad

In object Parsec, we declare mkMonad method:

object Parsec {
  def apply[E, T](parser: State[E] => Try[T]): Parsec[E, T] = parser(_)

  implicit def toFlatMapper[E, T, O](binder: Binder[E, T, O]): (T)=>Parsec[E, O] = binder.apply

  implicit def mkMonad[T]: Monad[({type P[A] = Parsec[T, A]})#P] =
    new Monad[({type P[A] = Parsec[T, A]})#P] {
      override def pure[A](element: A): Parsec[T, A] = Return(element)

      override def fmap[A, B](m: Parsec[T, A], f: A => B): Parsec[T, B] = m.ask(_).map(f)

      override def flatMap[A, B](m: Parsec[T, A], f: A => Parsec[T, B]): Parsec[T, B] = state => for {
        a <- m.ask(state)
        b <- f(a).ask(state)
      } yield b
    }

}

More

By the way, we have try monad, list monad, even future monad as:

class FutureSpec extends AsyncFlatSpec with Matchers {
  import jaskell.Monad.toMonad

  val future: Future[Double] = Future("success") *> Future(3.14) <:> { value => value * 2*2} <* Future("Right")

  "Pi" should "success a area of r=2 circle" in {
    future.map(value => value should be (3.14 * 2 * 2))
  }
}