Skip to content

Instantly share code, notes, and snippets.

@rerorero
Created February 4, 2015 11:01
Show Gist options
  • Save rerorero/6a90398fd1151ac939ab to your computer and use it in GitHub Desktop.
Save rerorero/6a90398fd1151ac939ab to your computer and use it in GitHub Desktop.
free monad sample1
import scalaz._
import Scalaz._
sealed trait LogF[A]
object Logging {
type Log[A] = Free[LogF, A]
implicit def logFFunctor[B]: Functor[LogF] = new Functor[LogF]{
def map[A,B](fa: LogF[A])(f: A => B): LogF[B] =
fa match {
case Debug(msg,a) => Debug(msg,f(a))
case Info(msg,a) => Info(msg,f(a))
case Warn(msg,a) => Warn(msg,f(a))
case Error(msg,a) => Error(msg,f(a))
}
}
implicit def logFToFree[A](logf: LogF[A]): Free[LogF,A] =
Free.liftF(logf)
case class Debug[A](msg: String, o: A) extends LogF[A]
case class Info[A](msg: String, o: A) extends LogF[A]
case class Warn[A](msg: String, o: A) extends LogF[A]
case class Error[A](msg: String, o: A) extends LogF[A]
object log {
def debug(msg: String): Log[Unit] = Debug(msg, ())
def info(msg: String): Log[Unit] = Info(msg, ())
def warn(msg: String): Log[Unit] = Warn(msg, ())
def error(msg: String): Log[Unit] = Error(msg, ())
}
}
object Println {
import Logging._
private def write(prefix: String, msg: String): Unit =
println(s"[$prefix] $msg")
private def debug(msg: String): Unit = write("DEBUG", msg)
private def info(msg: String): Unit = write("INFO", msg)
private def warn(msg: String): Unit = write("WARN", msg)
private def error(msg: String): Unit = write("ERROR", msg)
private val exe: LogF ~> Id = new (LogF ~> Id) {
def apply[B](l: LogF[B]): B = l match {
case Debug(msg,a) => { debug(msg); a }
case Info(msg,a) => { info(msg); a }
case Warn(msg,a) => { warn(msg); a }
case Error(msg,a) => { error(msg); a }
}
}
def apply[A](log: Log[A]): A =
log.runM(exe.apply[Log[A]])
}
/**
* Interpreter for SLF4J
*/
object SLF4J {
import Logging._
private val exe: LogF ~> Id = new (LogF ~> Id) {
def apply[B](l: LogF[B]): B = l match {
case Debug(msg,a) => { println("DEBUG ::: " + msg); println(a); a }
case Info(msg,a) => { println("INFO ::: " + msg); println(a); a }
case Warn(msg,a) => { println("WARN ::: " + msg); println(a); a }
case Error(msg,a) => { println("ERROR ::: " + msg); println(a); a }
}
}
def apply[A](log: Log[A]): A =
log.runM(exe.apply[Log[A]])
}
object LogTest {
import Logging.log
val program: Free[LogF, Unit] =
for {
x <- log.debug("yiaaaaa")
a <- log.info("fooo")
b <- log.error("OH NOES")
} yield b
def test() : Unit = {
SLF4J(program)
}
}
import scalaz.{~>, Id, Free, Functor}
sealed trait Query[A]
final case class ForEach[S,A](source: List[S], next: Ref[S] => A) extends Query[A]
final case class Filter[A](pred: Expr[Bool], next: Bool => A) extends Query[A]
final case class Select[S,A](expr: Expr[S], next: S => A) extends Query[A]
sealed trait Expr[A]
final case class Ref[A](name: String) extends Expr[A]
final case class Gt(left: Expr[Num], right: Expr[Num]) extends Expr[Bool]
final case class Lt(left: Expr[Num], right: Expr[Num]) extends Expr[Bool]
final case class Add(left: Expr[Num], right: Expr[Num]) extends Expr[Num]
final case class Num(value: Int) extends Expr[Num]
final case class Bool(value: Boolean) extends Expr[Bool]
// select a from someTable where a < 2
// ForEach(a <- someTable)
// Filter(a < 2)
// Select(a)
object Query {
implicit val queryFunctor: Functor[Query] = new Functor[Query] {
def map[A, B](fa: Query[A])(f: A => B): Query[B] =
fa match {
case ForEach(source, next) => ForEach(source, next andThen f)//(ref: Ref) => f(next(ref)))
case Filter(pred, next) => Filter(pred, bool => f(next(bool)))
case Select(expr, next) => Select(expr, next andThen f)//a => f(next(a)))
}
}
def forEach[S](source: List[S]) =
Free.liftF(ForEach(source, (ref: Ref[S]) => ref))
def filter(pred: Expr[Bool]) =
Free.liftF(Filter(pred, (bool: Bool) => bool) : Query[Bool])
def select[S](expr: Expr[S]) =
Free.liftF(Select(expr, (value: S) => value))
}
object QueryExample {
import Query._
val free =
for {
ref <- forEach(List(Num(1), Num(2), Num(3)))
f <- filter(Lt(ref, Num(3)))
v <- select(Add(ref, Num(4)))
} yield v
}
object Runner {
def apply[A]()
}
object QTest {
def test() {
println(QueryExample.free)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment