diff --git a/zio-interop-cats-tests/shared/src/test/scala/zio/interop/CatsMtlSpec.scala b/zio-interop-cats-tests/shared/src/test/scala/zio/interop/CatsMtlSpec.scala index 696bc4df..6671a18f 100644 --- a/zio-interop-cats-tests/shared/src/test/scala/zio/interop/CatsMtlSpec.scala +++ b/zio-interop-cats-tests/shared/src/test/scala/zio/interop/CatsMtlSpec.scala @@ -2,7 +2,6 @@ package zio.interop import cats.implicits.* import cats.mtl.laws.discipline.* -import cats.mtl.{ Handle, Raise } import zio.* import zio.interop.catz.* import zio.interop.catz.mtl.* @@ -13,11 +12,21 @@ class CatsMtlSpec extends ZioSpecBase { checkAllAsync( "Ask[ZIO[Ctx, Error, _]]", - implicit tc => AskTests[ZIO[Ctx, Error, _], ZEnvironment[Ctx]].ask[Ctx] + implicit tc => AskTests[ZIO[Ctx, Error, _], Ctx].ask[Ctx] ) checkAllAsync( "Local[ZIO[Ctx, Error, _]]", + implicit tc => LocalTests[ZIO[Ctx, Error, _], Ctx].local[Ctx, Int] + ) + + checkAllAsync( + "Ask[ZIO[Ctx, Error, _]] with ZEnvironment", + implicit tc => AskTests[ZIO[Ctx, Error, _], ZEnvironment[Ctx]].ask[Ctx] + ) + + checkAllAsync( + "Local[ZIO[Ctx, Error, _]] with ZEnvironment", implicit tc => LocalTests[ZIO[Ctx, Error, _], ZEnvironment[Ctx]].local[ZEnvironment[Ctx], Int] ) @@ -44,7 +53,4 @@ class CatsMtlSpec extends ZioSpecBase { "Handle[ZIO[Ctx, Error, _]]", implicit tc => HandleTests[ZIO[Ctx, Error, _], Error].handle[Int] ) - - def raiseSummoner[R, E] = Raise[ZIO[R, E, _], E] - def handleSummoner[R, E] = Handle[ZIO[R, E, _], E] } diff --git a/zio-interop-cats/shared/src/main/scala/zio/interop/catsmtl.scala b/zio-interop-cats/shared/src/main/scala/zio/interop/catsmtl.scala index 9df3f419..8addd05b 100644 --- a/zio-interop-cats/shared/src/main/scala/zio/interop/catsmtl.scala +++ b/zio-interop-cats/shared/src/main/scala/zio/interop/catsmtl.scala @@ -18,33 +18,35 @@ package zio.interop import cats.Applicative import cats.mtl.* -import zio.{ CanFail, FiberRef, ZEnvironment, ZIO } +import zio.{ CanFail, FiberRef, Tag, ZEnvironment, ZIO } import zio.internal.stacktracer.InteropTracer abstract class CatsMtlPlatform extends CatsMtlInstances -abstract class CatsMtlInstances { +abstract class CatsMtlInstances extends CatsMtlInstances1 { + implicit def zioHandle[R, E](implicit ev: Applicative[ZIO[R, E, _]]): Handle[ZIO[R, E, _], E] = + new Handle[ZIO[R, E, _], E] { + override def applicative: Applicative[ZIO[R, E, _]] = ev + override def raise[E2 <: E, A](e: E2): ZIO[R, E, A] = ZIO.fail(e) + override def handleWith[A](fa: ZIO[R, E, A])(f: E => ZIO[R, E, A]): ZIO[R, E, A] = + fa.catchAll(f)(implicitly[CanFail[E]], InteropTracer.newTrace(f)) + } - implicit def zioLocal[R, E](implicit ev: Applicative[ZIO[R, E, _]]): Local[ZIO[R, E, _], ZEnvironment[R]] = + implicit def zioZEnvLocal[R, E](implicit ev: Applicative[ZIO[R, E, _]]): Local[ZIO[R, E, _], ZEnvironment[R]] = new Local[ZIO[R, E, _], ZEnvironment[R]] { - override def applicative: Applicative[ZIO[R, E, _]] = ev - override def ask[E2 >: ZEnvironment[R]]: ZIO[R, E, E2] = ZIO.environment + override def applicative: Applicative[ZIO[R, E, _]] = ev + + override def ask[E2 >: ZEnvironment[R]]: ZIO[R, E, E2] = ZIO.environment + override def local[A](fa: ZIO[R, E, A])(f: ZEnvironment[R] => ZEnvironment[R]): ZIO[R, E, A] = fa.provideSomeEnvironment(f)(InteropTracer.newTrace(f)) } - implicit def zioAsk[R1, R <: R1, E](implicit ev: Applicative[ZIO[R, E, _]]): Ask[ZIO[R, E, _], ZEnvironment[R1]] = + implicit def zioZEnvAsk[R1, R <: R1, E](implicit ev: Applicative[ZIO[R, E, _]]): Ask[ZIO[R, E, _], ZEnvironment[R1]] = new Ask[ZIO[R, E, _], ZEnvironment[R1]] { - override def applicative: Applicative[ZIO[R, E, _]] = ev - override def ask[R2 >: ZEnvironment[R1]]: ZIO[R, E, R2] = ZIO.environment - } + override def applicative: Applicative[ZIO[R, E, _]] = ev - implicit def zioHandle[R, E](implicit ev: Applicative[ZIO[R, E, _]]): Handle[ZIO[R, E, _], E] = - new Handle[ZIO[R, E, _], E] { - override def applicative: Applicative[ZIO[R, E, _]] = ev - override def raise[E2 <: E, A](e: E2): ZIO[R, E, A] = ZIO.fail(e) - override def handleWith[A](fa: ZIO[R, E, A])(f: E => ZIO[R, E, A]): ZIO[R, E, A] = - fa.catchAll(f)(implicitly[CanFail[E]], InteropTracer.newTrace(f)) + override def ask[R2 >: ZEnvironment[R1]]: ZIO[R, E, R2] = ZIO.environment } implicit def fiberRefLocal[R, E](implicit @@ -65,3 +67,26 @@ abstract class CatsMtlInstances { } } + +trait CatsMtlInstances1 { + implicit def zioLocal[R: Tag, E](implicit ev: Applicative[ZIO[R, E, _]]): Local[ZIO[R, E, _], R] = + new Local[ZIO[R, E, _], R] { + override def applicative: Applicative[ZIO[R, E, _]] = ev + + override def ask[R1 >: R]: ZIO[R, E, R1] = ZIO.environment[R].map(_.get) + + override def local[A](fa: ZIO[R, E, A])(f: R => R): ZIO[R, E, A] = + fa.provideSomeEnvironment({ (env: ZEnvironment[R]) => + env.update(f) + })(InteropTracer.newTrace(f)) + } + + implicit def zioAsk[R1: Tag, R <: R1, E](implicit + ev: Applicative[ZIO[R, E, _]] + ): Ask[ZIO[R, E, _], R1] = + new Ask[ZIO[R, E, _], R1] { + override def applicative: Applicative[ZIO[R, E, _]] = ev + + override def ask[R2 >: R1]: ZIO[R, E, R2] = ZIO.environment[R1].map(_.get) + } +}