Created
February 4, 2015 11:01
-
-
Save rerorero/6a90398fd1151ac939ab to your computer and use it in GitHub Desktop.
free monad sample1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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