Last active
September 4, 2018 03:52
-
-
Save afsalthaj/4f2d666894a9f79dc0458ab390dc3d84 to your computer and use it in GitHub Desktop.
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
package com.telstra.dxmodel.api.interop | |
import cats.data.{EitherT, Writer, WriterT} | |
import cats.free.Free | |
import scala.util.Try | |
import cats.implicits._ | |
import cats.{Monad, ~>} | |
import com.telstra.dxmodel.api.interop | |
import scalaz.zio.IO | |
import com.telstra.dxmodel.instances.AllMonadInstances._ | |
sealed trait Alg[_] | |
object Alg { | |
type Action[A] = Free[Alg, A] | |
case object Action1 extends Alg[Int] | |
case object Action2 extends Alg[Int] | |
type ZIO[A] = IO[Nothing, A] | |
type ActionWithLog[A] = WriterT[ZIO, String, A] | |
type SafeActionWithLog[A] = EitherT[ActionWithLog, String, A] | |
object SafeActionWithLog { | |
def apply[A](f: => IO[String, A], msg: String): SafeActionWithLog[A] = { | |
EitherT[ActionWithLog, String, A] { WriterT[ZIO, String, Either[String, A]](f.attempt.map(t => (msg, t))) } | |
} | |
} | |
def action1: Action[Int] = Action1.asAction | |
def action2: Action[Int] = Action2.asAction | |
val interpreter: Alg ~> SafeActionWithLog = new (Alg ~> SafeActionWithLog){ | |
override def apply[A](fa: Alg[A]): SafeActionWithLog[A] = fa match { | |
case Action1 => SafeActionWithLog(IO.point(1), "Getting 1") | |
case Action2 => SafeActionWithLog(IO.fail("painful error"), "Failed") | |
} | |
} | |
def blaInterpreter(x: Alg ~> SafeActionWithLog) = new (Action ~> SafeActionWithLog) { | |
override def apply[A](fa: Action[A]): SafeActionWithLog[A] = | |
fa.foldMap(x) | |
} | |
} | |
object Logger { | |
import Alg._ | |
type Logger[A] = WriterT[Action, List[String], A] | |
object Logger { | |
def apply[A](msg: String, f: Action[A]): Logger[A] = | |
WriterT(f.map(t => (List(msg), t))) | |
} | |
implicit def toLoggerOps[T](x: Either[Throwable, T]) = LoggerOps(x) | |
} | |
final case class LoggerOps[T](val underlying: Either[Throwable, T]) extends AnyVal { | |
def ||>(msg: String) = | |
WriterT( | |
IO.point (( | |
List(msg), | |
underlying | |
)) | |
) | |
} | |
object Main extends App { | |
import Logger._ | |
import Alg._ | |
// Free algebra version. Looks nicer ! | |
val z: Free[Alg, Unit] = | |
for { | |
_ <- action1 | |
_ <- action1 | |
_ <- action1 | |
_ <- action1 | |
_ <- action1 | |
_ <- action2 | |
} yield () | |
val k= z.foldMap(interpreter).value.run.asIO.unsafeRunSync() | |
println(k) | |
// Result: Left(painful error) | |
// Finally tagless version - Oh oh! | |
val r = for { | |
_ <- EitherT { 4.asRight[Throwable] ||> "Getting 4" } | |
_ <- EitherT { 5.asRight[Throwable] ||> "Getting 5" } | |
_ <- EitherT { new Exception("Failed 1").asLeft[Int] ||> "Getting 6" } | |
_ <- EitherT { new Exception("Failed 2").asLeft[Int] ||> "Getting 7" } | |
} yield () | |
println(r.value.run.asIO.unsafeRunSync()) | |
// Result: (List(Getting 4, Getting 5, Getting 6),Left(java.lang.Exception: Failed 1)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment