Skip to content

Instantly share code, notes, and snippets.

@davidhoyt
Forked from trane/ringAroundTheMonad.scala
Last active August 29, 2015 14:27
Show Gist options
  • Save davidhoyt/efdb7712c99e062ce6ce to your computer and use it in GitHub Desktop.
Save davidhoyt/efdb7712c99e062ce6ce to your computer and use it in GitHub Desktop.
playing with Coyoneda+Free Monad for algebraic Rings.. and funsies
import algebra._, std.int._
import cats._, free._, Free._
import scala.language.implicitConversions
trait Expr[A]
case class Const[A](term: A) extends Expr[A]
case class Add[A](e1: Expr[A], e2: Expr[A])(implicit val r: Ring[A]) extends Expr[A]
type Exp[A] = FreeC[Expr, A]
implicit def int2App(i: Int): Expr[Int] =
Const(i)
def const[A](a: A): Exp[A] =
liftFC(Const(a))
def add[A : Ring](e1: Expr[A], e2: Expr[A]): Exp[A] =
liftFC(Add(e1, e2))
def liftExpr[A](e: Expr[A]): Exp[A] = e match {
case Const(e) => const(e)
case a @ Add(e1, e2) => add(e1, e2)(a.r)
}
val program: Exp[Int] =
for {
x <- add(1, 2)
} yield x
implicit object transform extends (Expr ~> Id) {
def apply[A](expr: Expr[A]): Id[A] = expr match {
case Const(a) => a
case a @ Add(e1: Expr[A], e2: Expr[A]) => a.r.plus(apply(e1), apply(e2))
}
}
// foldMap() does not work since Expr does not have an associated Functor.
// program.foldMap[Id](transform)
def compile[A](program: Exp[A])(implicit nat: Expr ~> Id): () => A = () =>
runFC(program)(nat)
val compiledProgram = compile(program)
println(compiledProgram())
println(compiledProgram())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment