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))
}
}