Stacking Free Monads - scala

I'm learning about the Free monads, and I've put together a simple example in Scala where I use them to define two domain specific languages.
The first monad deals with the side effects of a repository. I have implemented an interpreter that uses the state monad to manage the state, but in a real program I'd use a database.
The second monad deals with IO.
import cats.data.State
import cats.{Id, ~>}
import cats.free.Free
import cats.free.Free.liftF
final case class Todo(title: String, body: String)
def represent(todo: Todo) = s"${todo.title}: ${todo.body}"
sealed trait CRUDActionA[T]
final case class Find(key: String) extends CRUDActionA[Option[Todo]]
final case class Add(data: Todo) extends CRUDActionA[Unit]
type CRUDAction[T] = Free[CRUDActionA, T]
def find(key: String): CRUDAction[Option[Todo]] = liftF[CRUDActionA, Option[Todo]](Find(key))
def add(data: Todo): CRUDAction[Unit] = liftF[CRUDActionA, Unit](Add(data))
type TodosState[A] = State[List[Todo], A]
val repository: CRUDActionA ~> TodosState = new (CRUDActionA ~> TodosState) {
def apply[T](fa: CRUDActionA[T]): TodosState[T] = fa match {
case Add(todo) => State.modify(todos => todos :+ todo)
case Find(title) => State.inspect(todos => todos find (_.title == title))
}
}
sealed trait IOActionA[T]
final case class Out(str: String) extends IOActionA[Unit]
type IOAction[T] = Free[IOActionA, T]
def out(str: String): IOAction[Unit] = liftF[IOActionA, Unit](Out(str))
val io: IOActionA ~> Id = new (IOActionA ~> Id) {
override def apply[A](fa: IOActionA[A]): Id[A] = fa match {
case Out(todo) => println(todo)
}
}
Then, I can put together these two "programs"
def addNewTodo: Free[CRUDActionA, Option[Todo]] = for {
_ <- add(Todo(title = "Must do", body = "Must do something"))
todo <- find("Must do")
} yield todo
def outProgram(todo: Todo): IOAction[Unit] = for {
_ <- out(represent(todo))
} yield ()
And run them doing
val (_, mayBeTodo) = (addNewTodo foldMap repository run List()).value
outProgram(mayBeTodo.get).foldMap(io)
I understand this is far from ideal, and I'd like to write a program as and an interpreter that supports:
def fullProgram = for {
_ <- add(Todo(title = "Must do", body = "Must do something"))
todo <- find("Must do") // This is an option!!!
_ <- out(represent(todo)) // But represent expects a Todo
} yield ()
So the questions are:
How can I stack the two monads together into a "fullProgram"
How can I compose the two interpreters into a new interpreter?
How do I deal with the Option[Todo] returned by find, and then passed to
represent

Answer to questions 1 & 2:
type TodoApp[A] = Coproduct[IOActionA, CRUDActionA, A]
class CRUDActions[F[_]](implicit I: Inject[CRUDActionA, F]) {
def find(key: String): Free[F, Option[Todo]] = Free.inject[CRUDActionA, F](Find(key))
def add(data: Todo): Free[F, Unit] = Free.inject[CRUDActionA, F](Add(data))
}
object CRUDActions {
implicit def crudActions[F[_]](implicit I: Inject[CRUDActionA, F]): CRUDActions[F] = new CRUDActions[F]
}
class IOActions[F[_]](implicit I: Inject[IOActionA, F]) {
def out(str: String): Free[F, Unit] = Free.inject[IOActionA, F](Out(str))
}
object IOActions {
implicit def ioActions[F[_]](implicit I: Inject[IOActionA, F]): IOActions[F] = new IOActions[F]
}
def fullProgram(implicit C : CRUDActions[TodoApp], I : IOActions[TodoApp]): Free[TodoApp, Unit] = {
for {
_ <- C.add(Todo(title = "Must do", body = "Must do something"))
todo <- C.find("Must do")
_ <- I.out(represent(todo.get))
} yield ()
}
object ConsoleCatsInterpreter extends (IOActionA ~> Id) {
def apply[A](i: IOActionA[A]) = i match {
case Out(prompt) => println(prompt).asInstanceOf[A]
}
}
object MutableListCrudInterpreter extends (CRUDActionA ~> Id) {
val data = new ListBuffer[Todo]
override def apply[A](fa: CRUDActionA[A]): Id[A] = fa match {
case Add(todo) => data.append(todo).asInstanceOf[A]
case Find(title) => data.find( _.title == title).asInstanceOf[A]
}
}
val interpreter: TodoApp ~> Id = ConsoleCatsInterpreter or MutableListCrudInterpreter
fullProgram.foldMap(interpreter)

Related

Can I generate Scala code from a template (of sorts)?

Can I generate Scala code from a template (of sorts)?
I know how to do this in Racket/Scheme/Lisp, but not in Scala. Is this something Scala macros can do?
I want to have a code template where X varies. If I had this code template:
def funcX(a: ArgsX): Try[Seq[RowX]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.funcX(t, a)}
case _ => Failure(new MissingThingException)
}
and tokens Apple and Orange, a macro would take my template, replace the Xs, and produce:
def funcApple(a: ArgsApple): Try[Seq[RowApple]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.funcApple(t, a)}
case _ => Failure(new MissingThingException)
}
def funcOrange(a: ArgsOrange): Try[Seq[RowOrange]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.funcOrange(t, a)}
case _ => Failure(new MissingThingException)
}
Try macro annotation with tree transformer
#compileTimeOnly("enable macro paradise")
class generate extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro GenerateMacro.impl
}
object GenerateMacro {
def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
val trees = List("Apple", "Orange").map { s =>
val transformer = new Transformer {
override def transform(tree: Tree): Tree = tree match {
case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" if tname.toString.contains("X") =>
val tname1 = TermName(tname.toString.replace("X", s))
val tparams1 = tparams.map(super.transform(_))
val paramss1 = paramss.map(_.map(super.transform(_)))
val tpt1 = super.transform(tpt)
val expr1 = super.transform(expr)
q"$mods def $tname1[..$tparams1](...$paramss1): $tpt1 = $expr1"
case q"${tname: TermName} " if tname.toString.contains("X") =>
val tname1 = TermName(tname.toString.replace("X", s))
q"$tname1"
case tq"${tpname: TypeName} " if tpname.toString.contains("X") =>
val tpname1 = TypeName(tpname.toString.replace("X", s))
tq"$tpname1"
case q"$expr.$tname " if tname.toString.contains("X") =>
val expr1 = super.transform(expr)
val tname1 = TermName(tname.toString.replace("X", s))
q"$expr1.$tname1"
case tq"$ref.$tpname " if tpname.toString.contains("X") =>
val ref1 = super.transform(ref)
val tpname1 = TypeName(tpname.toString.replace("X", s))
tq"$ref1.$tpname1"
case t => super.transform(t)
}
}
transformer.transform(annottees.head)
}
q"..$trees"
}
}
#generate
def funcX(a: ArgsX): Try[Seq[RowX]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.funcX(t, a)}
case _ => Failure(new MissingThingException)
}
//Warning:scalac: {
// def funcApple(a: ArgsApple): Try[Seq[RowApple]] = w.getThing() match {
// case Some((t # (_: Thing))) => w.wrap(t)(Detail.funcApple(t, a))
// case _ => Failure(new MissingThingException())
// };
// def funcOrange(a: ArgsOrange): Try[Seq[RowOrange]] = w.getThing() match {
// case Some((t # (_: Thing))) => w.wrap(t)(Detail.funcOrange(t, a))
// case _ => Failure(new MissingThingException())
// };
// ()
//}
Also you can try approach with type class
def func[A <: Args](a: A)(implicit ar: ArgsRows[A]): Try[Seq[ar.R]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){Detail.func(t, a)}
case _ => Failure(new MissingThingException)
}
trait ArgsRows[A <: Args] {
type R <: Row
}
object ArgsRows {
type Aux[A <: Args, R0 <: Row] = ArgsRows[A] { type R = R0 }
implicit val apple: Aux[ArgsApple, RowApple] = null
implicit val orange: Aux[ArgsOrange, RowOrange] = null
}
sealed trait Args
trait ArgsApple extends Args
trait ArgsOrange extends Args
trait Thing
sealed trait Row
trait RowApple extends Row
trait RowOrange extends Row
object Detail {
def func[A <: Args](t: Thing, a: A)(implicit ar: ArgsRows[A]): ar.R = ???
}
class MissingThingException extends Throwable
trait W {
def wrap[R <: Row](t: Thing)(r: R): Try[Seq[R]] = ???
def getThing(): Option[Thing] = ???
}
val w: W = ???
In my opinion, it looks like you could pass your funcX function as a higher-order function. You could also combine it with currying to make a "function factory":
def funcX[A](f: (Thing, A) => RowX)(a: A): Try[Seq[RowX]] =
w.getThing() match {
case Some(t: Thing) => w.wrap(t){f(t,a)}
case _ => Failure(new MissingThingException)
}
Then you could use it to create instances of funcApple or funcOrange:
val funcApple: ArgsApple => Try[Seq[RowX]] = funcX(Detail.funcApple)
val funcOrange: ArgsOrange => Try[Seq[RowX]] = funcX(Detail.funcOrange)
funcApple(argsApple)
funcOrange(argsOrange)
I assumed the signature of Detail.funcApple and Detail.funcOrange is similar to (Thing, X) => RowX, but of course you could use different.
You may not actually need macros to achieve this, you can use a pattern match a generic type like this:
import scala.util.Try
def funcX[A](input :A) :Try[Seq[String]] = input match {
case x :String => Success(List(s"Input is a string: $input, call Detail.funcApple"))
case x :Int => Success(List(s"Input is an int, call Detail.funcOrange"))
}
scala> funcX("apple")
res3: scala.util.Try[Seq[String]] = Success(List(Input is a string: apple, call Detail.funcApple))
scala> funcX(11)
res4: scala.util.Try[Seq[String]] = Success(List(Input is an int, call Detail.funcOrange))

How to substitute objects in tree-like Scala case class instance with derived objects?

Suppose I have a set of case classes that represent constants, variables, and unary and binary operations on them, similar to one from "Case Classes and Pattern Matching" chapter in Programming in Scala:
abstract class Value {
def basicEvaluate(varArray: Array[Double]): Double
def evaluate(varArray: Array[Double]) = basicEvaluate(varArray)
}
case class Constant(d: Double) extends Value {
override def basicEvaluate(varArray: Array[Double]) = d
}
case class Variable(i: Int) extends Value {
override def basicEvaluate(varArray: Array[Double]) = varArray(i)
}
case class Add(v1: Value, v2: Value) extends Value {
override def basicEvaluate(varArray: Array[Double]) = v1.evaluate(varArray) + v2.evaluate(varArray)
}
...
Then, suppose I have some means to produce expression trees that reuse certain subexpressions many times, and I wish to be able to evaluate the expression efficiently, so that each distinct subexpression gets evaluated only once. For this reason, I introduce a trait
trait UsingCache extends Value {
var cached: Option[Double] = None
override def evaluate(varArray: Array[Double]) = {
if (cached == None) {
cached = Some(basicEvaluate(varArray))
}
cached.get
}
}
Then, I can do the following:
val expr = new Variable(0) with UsingCache
val expr2 = new Add(expr, expr) with UsingCache
expr2.evaluate(Array(5.0))
and it works.
My question is - how to implement a function def extend(value: Value): UsingCache which would recursively replace each Value in the tree with a corresponding .. with UsingCache object? I wish to keep this logic decoupled from the individual subclasses of Value (e.g., when I add a new operation, it shouldn't contain any code specific for caching). Is there some way to do this using implicit conversion? Or some ideas how to use Scala reflection (I'm using Scala 2.12)?
Try macro
def extend(value: Value): UsingCache = macro extendImpl
def extendImpl(c: blackbox.Context)(value: c.Tree): c.Tree = {
import c.universe._
def transformExprss(exprss: Seq[Seq[Tree]]): Seq[Seq[Tree]] =
exprss.map(_.map(expr => if (expr.tpe <:< typeOf[Value]) q"extend($expr)" else expr))
value match {
case q"$expr.$tname.apply(...$exprss)" =>
val exprss1 = transformExprss(exprss)
q"new $expr.${tname.toTypeName}(...$exprss1) with UsingCache"
case q"${tname: TermName}.apply(...$exprss)" =>
val exprss1 = transformExprss(exprss)
q"new ${tname.toTypeName}(...$exprss1) with UsingCache"
}
}
extend(Add(Constant(1.0), Variable(2)))
//Warning:scalac: performing macro expansion App.extend(App.Add.apply(App.Constant.apply(1.0), App.Variable.apply(2))) at ...
//Warning:scalac: {
// final class $anon extends App.Add(extend(App.Constant.apply(1.0)), extend(App.Variable.apply(2))) with UsingCache {
// def <init>() = {
// super.<init>();
// ()
// }
// };
// new $anon()
//}
//Warning:scalac: performing macro expansion App.extend(App.Constant.apply(1.0)) at ...
//Warning:scalac: {
// final class $anon extends App.Constant(1.0) with UsingCache {
// def <init>() = {
// super.<init>();
// ()
// }
// };
// new $anon()
//}
//Warning:scalac: performing macro expansion App.extend(App.Variable.apply(2)) at ...
//Warning:scalac: {
// final class $anon extends App.Variable(2) with UsingCache {
// def <init>() = {
// super.<init>();
// ()
// }
// };
// new $anon()
//}
Here is a solution that uses a stack to do a depth-first traversal. It is tail call optimized, so will not suffer from stack overflow. The OP also asked that old cached values be reused, so a map is used for memoization.
object CachedValueTest2 {
def main(args: Array[String]) = {
val expr1 = Add(Add(Constant(1), Add(Variable(1), Constant(1))), Add(Constant(2), Constant(2)))
println(extend(expr1))
val expr2 = Add(Add(Constant(1), Add(Add(Variable(2), Constant(1)), Constant(1))), Add(Constant(2), Add(Variable(1), Constant(2))))
println(extend(expr2))
}
def extend(value: Value): UsingCache = {
def replace(input: Value, stack: List[(Add, Option[UsingCache], Option[UsingCache])], map: Map[Value, UsingCache]): UsingCache = {
input match {
case in # Constant(d) =>
val (v, newMap) = map.get(in) match {
case Some(entry) => (entry, map)
case None =>
val entry = new Constant(d) with UsingCache
(entry, map + (in -> entry))
}
popStack(v, stack, newMap)
case in # Variable(i) =>
val (v, newMap) = map.get(in) match {
case Some(entry) => (entry, map)
case None =>
val entry = new Variable(i) with UsingCache
(entry, map + (in -> entry))
}
popStack(v, stack, newMap)
case in # Add(v1, v2) =>
map.get(in) match {
case Some(entry) => entry
case None => replace(v1, (in, None, None) :: stack, map)
}
}
}
def popStack(input: UsingCache, stack: List[(Add, Option[UsingCache], Option[UsingCache])], map: Map[Value, UsingCache]): UsingCache = {
stack match {
case head :: tail =>
head match {
case (add, None, None) =>
replace(add.v2, (add, Some(input), None) :: tail, map)
case (add, Some(v1), None) =>
val v = new Add(v1, input) with UsingCache
val newMap = map + (add -> v)
popStack(v, tail, newMap)
}
case Nil => input
}
}
replace(value, List(), Map())
}
abstract class Value {
def basicEvaluate(varArray: Array[Double]): Double
def evaluate(varArray: Array[Double]) = basicEvaluate(varArray)
}
case class Constant(d: Double) extends Value {
override def basicEvaluate(varArray: Array[Double]) = d
}
case class Variable(i: Int) extends Value {
override def basicEvaluate(varArray: Array[Double]) = varArray(i)
}
case class Add(v1: Value, v2: Value) extends Value {
override def basicEvaluate(varArray: Array[Double]) = v1.evaluate(varArray) + v2.evaluate(varArray)
}
trait UsingCache extends Value {
var caches : Map[Array[Double], Double] = Map()
override def evaluate(varArray: Array[Double]) = {
caches.get(varArray) match {
case Some(result) =>
result
case None =>
val result = basicEvaluate(varArray)
caches = caches + (varArray -> result)
result
}
}
}
}

How do I chain action and interpret them together with Scalaz?

I am trying to learn how to use FreeMonads to implement interpreters for my services.
Suppose I have
sealed trait ServiceAction[T] extends Product with Serializable
case class ConsumeCommand(cmd: AccruePoints) extends ServiceAction[AccruePointModel]
case class CreateEvent(evt: PointsAccruedEvent) extends ServiceAction[PointsAccruedEvent]
sealed trait LogAction[T] extends Product with Serializable
case class Info(msg: String) extends LogAction[Unit]
case class Error(msg: String) extends LogAction[Unit]
and a Monad of the action
type LogActionF[A] = Free[LogAction, A]
type ServiceActionF[A] = Free[ServiceAction, A]
Next, I define my service like this:
trait PointAccrualService {
def consume(cmd: AccruePoints): ServiceActionF[AccruePointModel] = Free.liftF(ConsumeCommand(cmd))
def emit(evt: PointsAccruedEvent) : ServiceActionF[PointsAccruedEvent] = Free.liftF(CreateEvent(evt))
}
and
trait LogService {
def info(msg: String) : LogActionF[Unit] = Free.liftF(Info(msg))
def error(msg: String) : LogActionF[Unit] = Free.liftF(Error(msg))
}
with an object of each
object LogService extends LogService
object PointAccrualService extends PointAccrualService
My LogServiceInterpreter is like this:
case class LogServiceConsoleInterpreter() extends LogServiceInterpreter {
def apply[A](action: LogActionF[A]): Task[A] = action.foldMap(handler)
protected def handler = new (LogAction ~> Task) {
override def apply[A](fa: LogAction[A]) = fa match {
case Info(m) =>
now(info(m))
case Error(m) =>
now(error(m))
}
}
def info(msg: String): Unit = {
println(s"INFO: $msg")
}
def error(msg: String): Unit = {
println(s"ERROR: $msg")
}
}
Similarly, my PointAccuralServiceInterpreter is like this:
case class PointAccuralServiceInterpreter() {
def apply[A] (action: ServiceActionF[A]) : Task[A] = action.foldMap(handler)
protected def handler = new (ServiceAction ~> Task) {
override def apply[A](fa: ServiceAction[A]): Task[A] = fa match {
case ConsumeCommand(cmd) => {
println("Service ConsumeCommand:" + cmd)
now(cmd)
}
case CreateEvent(evt) => {
println("Service CreateEvent:" + evt)
now(evt)
}
}
}
}
My logic is straightforward, I want to log, and consume my command and then create an event, sort of like an event sourcing:
val ret = for {
_ <- logService.info("Command: " + cmd)
model <- service.consume(cmd)
_ <- logService.info("Model: " + model)
evt <- service.emit(model.toEvent("200", "Event Sent"))
_ <- logService.info("Event:" + evt)
} yield evt
This code doesn't even compile actually.
What should I do from here? I think I am supposed to use Coproduct to chain them and execute this piece of logic by feeding my interpreter.
I found something here
https://groups.google.com/forum/#!topic/scalaz/sHxFsFpE86c
or it's said I can use Shapeless to do so
Folding a list of different types using Shapeless in Scala
They are all too complicated. All I want is, after I define my logic, how do I execute it?
Hope I put enough details here for an answer. I really want to learn this. Thanks
I slightly modified your code to create a self-contained running example. I also added a possible answer to your question, how to execute your program, following RĂșnar Bjarnason's ideas, using Scalaz 7.2. (I did not find the or operator for the natural transformations in Scalaz, so I added it here.)
I also added a few stubs to give your actions something to fiddle with and simplified your services to the handlers inside (since I had to create a new service for both languages combined). Furthermore I changed your Task.now{...} to Task{...} to create an asynchronous Task, which is executed on the last line of code.
Here is the full code:
import scala.language.{higherKinds, implicitConversions}
import scalaz._
import scalaz.concurrent.Task
/* Stubs */
case class AccruePoints()
case class AccruePointModel(cmd: AccruePoints) {
def toEvent(code: String, description: String): PointsAccruedEvent = PointsAccruedEvent(code, description)
}
case class PointsAccruedEvent(code: String, description: String)
/* Actions */
sealed trait ServiceAction[T] extends Product with Serializable
case class ConsumeCommand(cmd: AccruePoints) extends ServiceAction[AccruePointModel]
case class CreateEvent(evt: PointsAccruedEvent) extends ServiceAction[PointsAccruedEvent]
sealed trait LogAction[T] extends Product with Serializable
case class Info(msg: String) extends LogAction[Unit]
case class Error(msg: String) extends LogAction[Unit]
/* Handlers */
object PointAccuralServiceHandler extends (ServiceAction ~> Task) {
override def apply[A](fa: ServiceAction[A]): Task[A] = fa match {
case ConsumeCommand(cmd) => {
println("Service ConsumeCommand:" + cmd)
Task(consume(cmd))
}
case CreateEvent(evt) => {
println("Service CreateEvent:" + evt)
Task(evt)
}
}
def consume(cmd: AccruePoints): AccruePointModel =
AccruePointModel(cmd)
}
case object LogServiceConsoleHandler extends (LogAction ~> Task) {
override def apply[A](fa: LogAction[A]): Task[A] = fa match {
case Info(m) =>
Task(info(m))
case Error(m) =>
Task(error(m))
}
def info(msg: String): Unit = {
println(s"INFO: $msg")
}
def error(msg: String): Unit = {
println(s"ERROR: $msg")
}
}
/* Execution */
class Service[F[_]](implicit I1: Inject[ServiceAction, F], I2: Inject[LogAction, F]) {
def consume(cmd: AccruePoints): Free[F, AccruePointModel] = Free.liftF(I1(ConsumeCommand(cmd)))
def emit(evt: PointsAccruedEvent): Free[F, PointsAccruedEvent] = Free.liftF(I1(CreateEvent(evt)))
def info(msg: String): Free[F, Unit] = Free.liftF(I2(Info(msg)))
def error(msg: String): Free[F, Unit] = Free.liftF(I2(Error(msg)))
}
object Service {
implicit def instance[F[_]](implicit I1: Inject[ServiceAction, F], I2: Inject[LogAction, F]) = new Service[F]
}
def prg[F[_]](implicit service: Service[F]) = {
val cmd = AccruePoints()
for {
_ <- service.info("Command: " + cmd)
model <- service.consume(cmd)
_ <- service.info("Model: " + model)
evt <- service.emit(model.toEvent("200", "Event Sent"))
_ <- service.info("Event:" + evt)
} yield evt
}
type App[A] = Coproduct[ServiceAction, LogAction, A]
def or[F[_], G[_], H[_]](f: F ~> H, g: G ~> H) =
new (({type t[x] = Coproduct[F, G, x]})#t ~> H) {
override def apply[A](c: Coproduct[F, G, A]): H[A] = c.run match {
case -\/(fa) => f(fa)
case \/-(ga) => g(ga)
}
}
val app = prg[App]
val ret = app.foldMap(or(PointAccuralServiceHandler, LogServiceConsoleHandler))
ret.unsafePerformSync

Combine different "containers" in cats XorT

For example, we have some services with different "containers" Future and Option:
//first service with Future
class FirstService {
getData(): XorT[Future, ServiceError, SomeData]
}
//second service with Optin
class SecondService {
getData(): XorT[Option, ServiceError, SomeData]
}
How do we can combine them to use one for comprehension to avoid type mismatch?
val result = for {
data1 <- firstService.getData()
data2 <- secondService.getData() // type mismatch required XorT[Future, ServiceError, SomeData]
} yield mergeResult(data1, data2)
XorT[F, A, B] is just a convenient wrapper over F[A Xor B], so you question essentially is: how to combine a Future and an Option. Because you still have to return a Future in some form, this mainly becomes : how to handle the Option.
There are several possibilities :
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import cats.data.XorT
import cats.implicits._
type ServiceError = String
type FutureErrorOr[A] = XorT[Future, ServiceError, A]
val fXorT: FutureErrorOr[Int] = XorT.right(Future.successful(1))
val oXorT: XorT[Option, ServiceError, Int] = XorT.right(1.some)
Turn the Option into a Future (None to Future.failed) :
val opt2fut: FutureErrorOr[Int] =
XorT(oXorT.value.fold(
Future.failed[ServiceError Xor Int](new NoSuchElementException())(
Future.successful _))
for { a <- fXort; b <- opt2fut } yield a + b
Turn the Option into a ServiceError Xor ? (None to Xor.Left) :
val opt2xor: FutureErrorOr[Int] =
XorT.fromXor[Future](oXorT.value.getOrElse("no elem".left))
for { a <- fXort; b <- opt2xor } yield a + b
Change your return type to XorT[Future, ServiceError, Option[X]] (this might not be useful if you need to use the X in the rest of the for comprehension) :
val optInside: FutureErrorOr[Option[Int]] =
XorT.fromXor[Future](oXorT.value.sequenceU)
for { a <- fXorT; b <- optInside } yield b.map(_ + a)
One of the possible ways to solve this problem make common Container monad for different types (Future, Option):
trait Container[+A] {
def map[B](f: A => B): Container[B]
def flatMap[B](f: A => Container[B]): Container[B]
}
// Empty container for value
class EmptyContainer[+A](value: A) extends Container[A] {
override def map[B](f: (A) => B): Container[B] = new EmptyContainer[B](f(value))
override def flatMap[B](f: (A) => Container[B]): Container[B] = f(value)
}
// Implement container for Option
class OptionContainer[+A](option: Option[A]) extends Container[A] {
override def map[B](f: (A) => B): Container[B] = new OptionContainer[B](option.map(f))
override def flatMap[B](f: (A) => Container[B]): Container[B] = option match {
case Some(value) => f(value)
case None => new OptionContainer[B](None)
}
}
// Implement container for Future
class FutureContainer[+A](future: Future[A]) extends Container[A] {
override def map[B](f: (A) => B): Container[B] = new FutureContainer[B](future.map(f))
// TODO: can be better!!!
override def flatMap[B](f: (A) => Container[B]): Container[B] = {
val promise = Promise[B]()
future.onComplete {
case Success(a) => f(a).map(b => promise.success(b))
case Failure(exception) => promise.failure(exception)
}
new FutureContainer[B](promise.future)
}
}
You can add an own implementation for any others types.
// Monad for Container
object Container {
implicit def monad = new Monad[Container] {
def flatMap[A, B](fa: Container[A])(f: (A) => Container[B]): Container[B] = fa.flatMap(f)
def pure[A](x: A): Container[A] = new EmptyContainer[A](x)
}
}
Our service now has view:
class SomeContainerService {
def getSomeDate(): XorT[Container, Error, SomeData] =
XorT.right(Option(SomeData()).toContainer)
def getRemoteDate(): XorT[Container, Error, SomeData] =
XorT.right(Future(SomeData()).toContainer)
}
Extensions methods for both future and option:
def toContainer = OptionContainer(option)
def toContainer = FutureContainer(future)
And for-comprehension work fine:
val result: XorT[Container, Error, SomeData] = for {
data1 <- someContainerService.getRemoteDate() // future
data2 <- someContainerService.getSomeDate() // option
} yield {
mergeResult(data1, data2)
}

Define a MongoRecord in Lift with a Map inside it

I cannot find the way to define a MongoRecord with a Map[String,String] field inside it in Lift - MongoRecord.
The Lift documentation says:
All standard Record Fields are supported. There is also support for Mongo specific types; ObjectId, UUID, Pattern, List, and Map.
How can I define Map and List fields?
I defined a BsonRecordMapField:
class BsonRecordMapField[OwnerType <: BsonRecord[OwnerType], SubRecordType <: BsonRecord[SubRecordType]]
(rec: OwnerType, valueMeta: BsonMetaRecord[SubRecordType])(implicit mf: Manifest[SubRecordType])
extends MongoMapField[OwnerType, SubRecordType](rec: OwnerType) {
import scala.collection.JavaConversions._
override def asDBObject: DBObject = {
val javaMap = new HashMap[String, DBObject]()
for ((key, element) <- value) {
javaMap.put(key.asInstanceOf[String], element.asDBObject)
}
val dbl = new BasicDBObject(javaMap)
dbl
}
override def setFromDBObject(dbo: DBObject): Box[Map[String, SubRecordType]] = {
val mapResult: Map[String, SubRecordType] = (for ((key, dboEl) <- dbo.toMap.toSeq) yield (key.asInstanceOf[String], valueMeta.fromDBObject(dboEl.asInstanceOf[DBObject]))).toMap
setBox(Full(mapResult))
}
override def asJValue = {
val fieldList = (for ((key, elem) <- value) yield JField(key, elem.asJValue)).toList
JObject(fieldList)
}
override def setFromJValue(jvalue: JValue) = jvalue match {
case JNothing | JNull if optional_? => setBox(Empty)
case JObject(fieldList) => val retrievedMap = fieldList.map {
field =>
val key = field.name
val valRetrieved = valueMeta.fromJValue(field.value) openOr valueMeta.createRecord
(key, valRetrieved)
}.toMap
setBox(Full(retrievedMap))
case other => setBox(FieldHelpers.expectedA("JObject", other))
}
}
This is the implicit query for Rogue:
class BsonRecordMapQueryField[M <: BsonRecord[M], B <: BsonRecord[B]](val field: BsonRecordMapField[M, B])(implicit mf: Manifest[B]) {
def at(key: String): BsonRecordField[M, B] = {
val listBox = field.setFromJValue(JObject(List(JField("notExisting", JInt(0)))))
val rec = listBox.open_!.head._2
new BsonRecordField[M, B](field.owner, rec.meta)(mf) {
override def name = field.name + "." + key
}
}
}
object ExtendedRogue extends Rogue {
implicit def bsonRecordMapFieldToBsonRecordMapQueryField[M <: BsonRecord[M], B <: BsonRecord[B]](f: BsonRecordMapField[M, B])(implicit mf: Manifest[B]): BsonRecordMapQueryField[M, B] = new BsonRecordMapQueryField[M, B](f) (mf)
}
You can use the at operator in map now.
What about MongoMapField?