Skip to content

Instantly share code, notes, and snippets.

@a2mz
Forked from kciesielski/freemonads.scala
Created August 12, 2017 05:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save a2mz/5e863f504c45720d5f7a50ded6a5f094 to your computer and use it in GitHub Desktop.
Save a2mz/5e863f504c45720d5f7a50ded6a5f094 to your computer and use it in GitHub Desktop.
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