Advertisement
Guest User

Untitled

a guest
Nov 30th, 2014
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.44 KB | None | 0 0
  1. trait Functor[F[_]] {
  2.   def fmap[A, B](f: A => B)(F: F[A]): F[B]
  3. }
  4.  
  5. trait Monad[F[_]] extends Functor[F] {
  6.   def point[A](a: A): F[A]
  7.   def bind[A, B](f: A => F[B])(F: F[A]): F[B]
  8.   def fmap[A, B](f: A => B)(F: F[A]): F[B] =
  9.     bind((a: A) => point(f(a)))(F)
  10. }
  11.  
  12. abstract class Free[F[_]: Functor, A]
  13. case class Done[F[_]: Functor, A](a: A) extends Free[F, A]
  14. case class More[F[_]: Functor, A](fa: F[Free[F, A]]) extends Free[F, A]
  15.  
  16. object Syntax {
  17.   implicit class FunctorSyntax[F[_], A](fa: F[A])(implicit F: Functor[F]) {
  18.     def fmap[B](f: A => B): F[B] = F.fmap(f)(fa)
  19.     def map[B](f: A => B): F[B] = fmap(f)
  20.   }
  21.  
  22.   implicit class MonadSyntax[F[_], A](fa: F[A])(implicit F: Monad[F]) {
  23.     def bind[B](f: A => F[B]): F[B] = F.bind(f)(fa)
  24.     def flatMap[B](f: A => F[B]): F[B] = bind(f)
  25.   }
  26. }
  27.  
  28. object Instances {
  29.   import Syntax._
  30.  
  31.   implicit def FreeMonad[F[_]: Functor] = new Monad[({type λ[a] = Free[F, a]})#λ] {
  32.     def point[A](a: A): Free[F, A] = Done(a)
  33.     def bind[A, B](f: A => Free[F, B])(Fa: Free[F, A]): Free[F, B] =
  34.       Fa match {
  35.         case Done(a)  => f(a)
  36.         case More(fa) => More(fa fmap (free => bind(f)(free)))
  37.       }
  38.   }
  39. }
  40.  
  41. object Algebra {
  42.   sealed trait Operation[A]
  43.   case class Addition[A](lhs: Int, rhs: Int, a: Int => A) extends Operation[A]
  44.   case class Subtraction[A](lhs: Int, rhs: Int, a: Int => A) extends Operation[A]
  45.  
  46.   implicit val OperationFunctor = new Functor[Operation] {
  47.     def fmap[A, B](f: A => B)(F: Operation[A]): Operation[B] =
  48.       F match {
  49.         case Addition(lhs, rhs, a)    => Addition(lhs, rhs, x => f(a(x)))
  50.         case Subtraction(lhs, rhs, a) => Subtraction(lhs, rhs, x => f(a(x)))
  51.       }
  52.   }
  53.  
  54.   object Operation {
  55.     def add(lhs: Int, rhs: Int): Free[Operation, Int] =
  56.       More(Addition(lhs, rhs, res => Done(res)))
  57.  
  58.     def sub(lhs: Int, rhs: Int): Free[Operation, Int] =
  59.       More(Subtraction(lhs, rhs, res => Done(res)))
  60.  
  61.     def run[A](operation: Free[Operation, A]): A =
  62.       operation match {
  63.         case Done(result)                   => result
  64.         case More(Addition(lhs, rhs, f))    => run(f(lhs + rhs))
  65.         case More(Subtraction(lhs, rhs, f)) => run(f(lhs - rhs))
  66.       }
  67.   }
  68.  
  69.   def example: Unit = {
  70.     import Operation._
  71.     import Instances._
  72.     import Syntax._
  73.  
  74.     val operations = for {
  75.       x1 <- add(4, 4)
  76.       x2 <- add(3, 3)
  77.       x3 <- sub(x1, x2)
  78.     } yield x3
  79.  
  80.     println(run(operations))
  81.   }
  82. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement