Created
June 6, 2016 22:07
-
-
Save ashic/345ef1136d2d7c707f20d062616d2f6c to your computer and use it in GitHub Desktop.
Free with futures and error handling
This file contains hidden or 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 Model._ | |
| import OpOps._ | |
| import cats.data.XorT | |
| import cats.free.Free | |
| import cats.~> | |
| import scala.concurrent.{Await, ExecutionContext, Future} | |
| object OpOps { | |
| implicit def toFree[A](op:Op[A]) : Free[Op, A] = | |
| Free.liftF(op) | |
| } | |
| object ProfileStore { | |
| def load(id:Int)(implicit ec:ExecutionContext) : Future[Profile] = Future { | |
| if(id == 42) throw new Exception("lala") | |
| Profile(id, "someName") | |
| } | |
| def save(p:Profile)(implicit ec:ExecutionContext) : Future[Profile] = Future {p} | |
| } | |
| object Model { | |
| sealed trait Op[A] | |
| type AppResult[A] = XorT[Future, Throwable, A] | |
| case class Profile(id:Int, name:String) | |
| case class loadProfile(id:Int) extends Op[Profile] | |
| case class saveProfile(p:Profile) extends Op[Profile] | |
| case class log(msg:String) extends Op[Unit] | |
| import cats.implicits._ | |
| import scala.concurrent.ExecutionContext.Implicits.global | |
| val futureInterpreter = new (Op ~> AppResult) { | |
| override def apply[A](fa: Op[A]): AppResult[A] = fa match { | |
| case loadProfile(id) => ProfileStore.load(id).attemptT | |
| case saveProfile(p:Profile) => ProfileStore.save(p).attemptT | |
| case log(msg:String) => Future{println(msg)}.attemptT | |
| } | |
| } | |
| def program(id:Int, newName:String): Free[Op, Profile] = for { | |
| p <- loadProfile(id) | |
| _ <- log(s"loaded profile with name ${p.name}") | |
| p2 <- saveProfile(p.copy(name=newName)) | |
| _ <- log(s"saved profile with name ${p2.name}") | |
| } yield p2 | |
| } | |
| object MyApp2 extends App { | |
| import scala.concurrent.ExecutionContext.Implicits.global | |
| import cats.implicits._ | |
| import scala.concurrent.duration._ | |
| val p1f : XorT[Future, Throwable, Profile] = program(20, "john").foldMap(futureInterpreter) | |
| val p1 = Await.result(p1f.value, 2 seconds) | |
| println(p1) //prints Right[Profile] | |
| val p2f : XorT[Future, Throwable, Profile] = program(42, "james").foldMap(futureInterpreter) | |
| val p2 = Await.result(p2f.value, 2 seconds) | |
| println(p2) //prints Left[Exception] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment