Skip to content

Instantly share code, notes, and snippets.

@yasuabe
Created January 31, 2019 04:54
sample code of Cats Effect LiftIO.liftIO
package cats_effect_typeclass_exericise.liftio
import java.time.format.DateTimeFormatter
import cats.data.{Chain, Kleisli, WriterT}
import cats.effect._
import scala.language.higherKinds
import scala.util.Try
import LiftIODemoUtil._
import cats.instances.either._
object LiftIODemoUtil {
val formatter = DateTimeFormatter.ofPattern("mm:ss")
def putIn(milli: Int, s: Any): String = {
Thread.sleep(milli)
val threadId = Thread.currentThread.getId
val currentMinSec = java.time.LocalTime.now.format(formatter)
println(s"in thread($threadId) at $currentMinSec): $s")
s.toString
}
def putLine(s: Any): String = putIn(1000, s)
def putIn1(s: Any): String = putIn(1000, s)
def putNow(s: Any): String = putIn(0, s)
def putRnd(s: Any): String = putIn((math.random * 1000 + 500).toInt, s)
// Either[Throwable, ?] の LiftIO インスタンスがスコープにあれば...
type ErrorOr[T] = Either[Throwable, T]
implicit val errorOrLiftIO: LiftIO[ErrorOr] = new LiftIO[ErrorOr] {
def liftIO[A](ioa: IO[A]): ErrorOr[A] = ioa.attempt.unsafeRunSync()
}
}
object LiftIOKleisliDemo extends IOApp {
type MyKleisli[T] = Kleisli[ErrorOr, String, T]
def tryParse(s: String): ErrorOr[Int] = Try(s.toInt).toEither
// Either[Throwable, ?] の LiftIO インスタンスがスコープにあれば
// Kleisli との合成インスタンスが暗黙に提供される
def testLiftIO(ios: IO[String])(implicit L: LiftIO[MyKleisli]): MyKleisli[Int] =
L.liftIO(ios).flatMapF(tryParse)
def run(args: List[String]): IO[ExitCode] = {
putLine(testLiftIO(IO("100")).run("dummy")) // Right(100)
putLine(testLiftIO(IO("NaN")).run("dummy")) // Left(NumberFormatException: For input string: "NaN")
putLine(testLiftIO(IO.raiseError(new Exception("boom!"))).run("dummy")) // Left(Exception: boom!)
IO(ExitCode.Success)
}
}
object LiftIOWriterTDemo {
type MyWriterT[T] = WriterT[ErrorOr, Chain[String], T]
def tryParse(s: String): ErrorOr[Int] =
Try { putNow(s"parsing $s"); s.toInt }.toEither
// Either[Throwable, ?] の LiftIO インスタンスさえスコープにあれば
// WriterT との合成インスタンスが暗黙に提供される
def testWriterT(ios: IO[String])(implicit L: LiftIO[MyWriterT]): MyWriterT[Int] =
L.liftIO(ios)
.tell(Chain("log: hello"))
.flatMap(x => WriterT.liftF(tryParse(x)))
def main(args: Array[String]): Unit = {
val ios = IO { putNow("now, ios's block is being executed"); "1234" }
putLine("ios is initialized, but execution of its block is deferred")
putLine(testWriterT(ios).run)
}
// in thread(1) at 49:18): ios is initialized, but execution of its block is deferred
// in thread(1) at 49:19): now, ios's block is being executed
// in thread(1) at 49:19): parsing 1234
// in thread(1) at 49:20): Right((Chain(log: hello),1234))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment