cats-mtl
, but what if you need to eventually provide a context and convert reader-like G
to a non-reader F
?
i usually use the former, and usually add
trait Train[F[_]] {
def toot(): F[Unit]
def mapK[G[_]](f: F ~> G): Train[G]
}
(cats-tagless can auto-generate these also)
Kleisli
vs. ApplicativeAsk
, that's one choice
F
s with different contexts.Lift
/Unlift
classes for conversion back and forth.ConnectionIO
and second to Kleisli[ConnectionIO, ...]
, both with its own lifts-unlifts
class BizLogic[F[_]](alg1: Alg1[F], alg2[Kleisli[F, Dependency]])
? because something like that would be difficult.
def withRequestId[F[_], G[_] : WithRun[*[_], F, RequestId[F]](routes: HttpRoutes[F]): HttpRoutes[G]
the former is more flexible, although it is likely that only Kleisli
has a WithRun
instance i'm guessing.
it's a familiarity issue, like you said. i think more folks would understand the Kleisli
version since it is more "concrete"
there's the evalMap(f: A => F[B]): Resource[F, A] => Resource[F, B] = _.flatMap(a => Resource.liftF(f(a)))
combinator that lifts the output of f
into an "inner" Resource
.
what about a different combinator that uses the first Resource
to create the next, where the first can be released: evalUse(f: A => F[B]): Resource[F, A] => Resource[F, B] = rfa => Resource.liftF(rfa.use(f))
?
def multiRace[F[_]: Concurrent, A](fas: List[F[A]]): F[A] = {
def spawn[B](fa: F[B]): Resource[F, Unit] =
Resource.make(fa.start)(_.cancel).void
def finish(fa: F[A], d: Deferred[F, Either[Throwable, A]]): F[Unit] =
fa.attempt.flatMap(d.complete)
Deferred[F, Either[Throwable, A]]
.flatMap { result =>
fas
.traverse(fa => spawn(finish(fa, result)))
.use(_ => result.get.rethrow)
}
}
def program(i: Int) = {
for {
wait <- IO(scala.util.Random.nextInt(1000))
_ <- IO(println(s"program $i waiting for $wait millis"))
_ <- IO.sleep(wait.millis)
_ <- IO(println(s"program $i finished"))
} yield i
}.guarantee(IO(println(s"program $i finalised")))
def test = multiRace(List.range(0, 5).map(program)).unsafeRunSync
ConcurrentEffect
for IorT
or am I missing something?