Free Monads example
package com.softwaremill.freemonads | |
import cats.free.Free | |
import cats.~> | |
import cats._, cats.std.all._ | |
import scala.concurrent.ExecutionContext.Implicits.global | |
import scala.concurrent.Future | |
sealed trait External[A] | |
case class Tickets(count: Int) extends AnyVal | |
case class InvokeTicketingService(count: Int) extends External[Tickets] | |
case class UserTicketsRequest(ticketCount: Int) | |
object GetTicketsExample { | |
def purchaseTickets(input: UserTicketsRequest): Free[External, Option[Tickets]] = { | |
if (input.ticketCount > 0) { | |
// creates a "Suspend" node | |
Free.liftF(InvokeTicketingService(input.ticketCount)).map(Some(_)) | |
} else { | |
Free.pure(None) | |
} | |
} | |
def bonusTickets(purchased: Option[Tickets]): Free[External, Option[Tickets]] = { | |
if (purchased.exists(_.count > 10)) { | |
Free.liftF(InvokeTicketingService(1)).map(Some(_)) | |
} else { | |
Free.pure(None) | |
} | |
} | |
def formatResponse(purchased: Option[Tickets], bonus: Option[Tickets]): String = | |
s"Purchased tickets: $purchased, bonus: $bonus" | |
val input = UserTicketsRequest(11) | |
val logic: Free[External, String] = for { | |
purchased <- purchaseTickets(input) | |
bonus <- bonusTickets(purchased) | |
} yield formatResponse(purchased, bonus) | |
val externalToServiceInvoker = new (External ~> Future) { | |
override def apply[A](e: External[A]): Future[A] = e match { | |
case InvokeTicketingService(c) => serviceInvoker.run(s"/tkts?count=$c") | |
} | |
} | |
val result = logic.foldMap(externalToServiceInvoker) | |
result.foreach(println) | |
object serviceInvoker { | |
def run(path: String) = { | |
Future { | |
Tickets(11) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
prayagupd commentedJun 19, 2018
•
edited
hi @kciesielski can you please mention the cat dependencies required for above code snippet as well?
I could not find
cats.std.all._
in following dependencies,I found
alleycats.std.all._
but not sure if thats correct. I get following compilation error[error] /Users/prayagupd/buybest/learnyouascala.fm/9_error_handling/src/test/scala/FreeMonad.scala:103:29: could not find implicit value for parameter M: cats.Monad[scala.concurrent.Future] [error] val result = logic.foldMap(externalToServiceInvoker) [error] ^ [error] three errors found [error] (test:compileIncremental) Compilation failed [error] Total time: 6 s, completed Jun 18, 2018 10:18:56 PM