From a0d8a34fc478a5f457f989be168617a999d9d4c4 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Thu, 3 Aug 2023 05:38:13 +0000 Subject: [PATCH 1/3] Add `Raise#fromEither` and friends --- core/src/main/scala/cats/mtl/Ask.scala | 4 +++- core/src/main/scala/cats/mtl/Raise.scala | 4 ++++ core/src/main/scala/cats/mtl/Stateful.scala | 8 +++++++- core/src/main/scala/cats/mtl/Tell.scala | 4 +++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/cats/mtl/Ask.scala b/core/src/main/scala/cats/mtl/Ask.scala index 8c7928ed..ee26c18c 100644 --- a/core/src/main/scala/cats/mtl/Ask.scala +++ b/core/src/main/scala/cats/mtl/Ask.scala @@ -17,7 +17,7 @@ package cats package mtl -import cats.data.{Kleisli, ReaderWriterStateT => RWST} +import cats.data.{Kleisli, Reader, ReaderWriterStateT => RWST} import cats.mtl.Ask.{const, AskImpl} import cats.syntax.all._ @@ -51,6 +51,8 @@ trait Ask[F[_], +E] extends Serializable { def ask[E2 >: E]: F[E2] def reader[A](f: E => A): F[A] = applicative.map(ask)(f) + + def fromReader[A](ra: Reader[E, A]): F[A] = reader(ra.run) } private[mtl] trait AskForMonadPartialOrder[F[_], G[_], E] extends Ask[G, E] { diff --git a/core/src/main/scala/cats/mtl/Raise.scala b/core/src/main/scala/cats/mtl/Raise.scala index 9eca79b7..a6a017d0 100644 --- a/core/src/main/scala/cats/mtl/Raise.scala +++ b/core/src/main/scala/cats/mtl/Raise.scala @@ -79,6 +79,10 @@ trait Raise[F[_], -E] extends Serializable { def ensure[E2 <: E, A](fa: F[A])(error: => E2)(predicate: A => Boolean)( implicit A: Monad[F]): F[A] = A.flatMap(fa)(a => if (predicate(a)) A.pure(a) else raise(error)) + + def fromEither[A](ea: Either[E, A])(implicit F: Applicative[F]): F[A] = + ea.fold(raise, F.pure) + } private[mtl] trait RaiseMonadPartialOrder[F[_], G[_], E] extends Raise[G, E] { diff --git a/core/src/main/scala/cats/mtl/Stateful.scala b/core/src/main/scala/cats/mtl/Stateful.scala index bca941e5..3a875dcc 100644 --- a/core/src/main/scala/cats/mtl/Stateful.scala +++ b/core/src/main/scala/cats/mtl/Stateful.scala @@ -17,7 +17,7 @@ package cats package mtl -import cats.data.{ReaderWriterStateT => RWST, StateT} +import cats.data.{ReaderWriterStateT => RWST, State, StateT} import scala.annotation.implicitNotFound @@ -64,6 +64,12 @@ trait Stateful[F[_], S] extends Serializable { def get: F[S] def set(s: S): F[Unit] + + def fromState[A](state: State[S, A]): F[A] = + monad.flatMap(get) { s0 => + val (s1, a) = state.run(s0).value + monad.as(set(s1), a) + } } private[mtl] trait LowPriorityStatefulInstances { diff --git a/core/src/main/scala/cats/mtl/Tell.scala b/core/src/main/scala/cats/mtl/Tell.scala index 3cfe4c14..b8df0cb1 100644 --- a/core/src/main/scala/cats/mtl/Tell.scala +++ b/core/src/main/scala/cats/mtl/Tell.scala @@ -17,7 +17,7 @@ package cats package mtl -import cats.data.{ReaderWriterStateT => RWST, WriterT} +import cats.data.{ReaderWriterStateT => RWST, Writer, WriterT} import scala.annotation.implicitNotFound @@ -47,6 +47,8 @@ trait Tell[F[_], -L] extends Serializable { def writer[A](a: A, l: L): F[A] = functor.as(tell(l), a) def tuple[A](ta: (L, A)): F[A] = writer(ta._2, ta._1) + + def fromWriter[L2 <: L, A](wa: Writer[L2, A]): F[A] = tuple(wa.run) } private[mtl] trait TellMonadPartialOrder[F[_], G[_], L] extends Tell[G, L] { From 335d04efd87cd57cdcad1ce62044d27363e15364 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Tue, 28 Nov 2023 04:29:22 +0000 Subject: [PATCH 2/3] Add transformer lifters, h/t @valencik --- core/src/main/scala/cats/mtl/Ask.scala | 3 +++ core/src/main/scala/cats/mtl/Raise.scala | 3 +++ core/src/main/scala/cats/mtl/Stateful.scala | 7 +++++++ core/src/main/scala/cats/mtl/Tell.scala | 3 +++ 4 files changed, 16 insertions(+) diff --git a/core/src/main/scala/cats/mtl/Ask.scala b/core/src/main/scala/cats/mtl/Ask.scala index ee26c18c..98f4f2ca 100644 --- a/core/src/main/scala/cats/mtl/Ask.scala +++ b/core/src/main/scala/cats/mtl/Ask.scala @@ -53,6 +53,9 @@ trait Ask[F[_], +E] extends Serializable { def reader[A](f: E => A): F[A] = applicative.map(ask)(f) def fromReader[A](ra: Reader[E, A]): F[A] = reader(ra.run) + + def fromKleisli[A](ka: Kleisli[F, E, A])(implicit F: FlatMap[F]): F[A] = + ask.flatMap(ka.run(_)) } private[mtl] trait AskForMonadPartialOrder[F[_], G[_], E] extends Ask[G, E] { diff --git a/core/src/main/scala/cats/mtl/Raise.scala b/core/src/main/scala/cats/mtl/Raise.scala index a6a017d0..11ca8d6c 100644 --- a/core/src/main/scala/cats/mtl/Raise.scala +++ b/core/src/main/scala/cats/mtl/Raise.scala @@ -83,6 +83,9 @@ trait Raise[F[_], -E] extends Serializable { def fromEither[A](ea: Either[E, A])(implicit F: Applicative[F]): F[A] = ea.fold(raise, F.pure) + def fromEitherT[E2 <: E, A](ea: EitherT[F, E2, A])(implicit F: Monad[F]): F[A] = + F.flatMap(ea.value)(fromEither(_)) + } private[mtl] trait RaiseMonadPartialOrder[F[_], G[_], E] extends Raise[G, E] { diff --git a/core/src/main/scala/cats/mtl/Stateful.scala b/core/src/main/scala/cats/mtl/Stateful.scala index 3a875dcc..13dafd4d 100644 --- a/core/src/main/scala/cats/mtl/Stateful.scala +++ b/core/src/main/scala/cats/mtl/Stateful.scala @@ -70,6 +70,13 @@ trait Stateful[F[_], S] extends Serializable { val (s1, a) = state.run(s0).value monad.as(set(s1), a) } + + def fromStateT[A](state: StateT[F, S, A]): F[A] = + monad.flatMap(get) { s0 => + monad.flatMap(state.run(s0)(monad)) { case (s1, a) => + monad.as(set(s1), a) + } + } } private[mtl] trait LowPriorityStatefulInstances { diff --git a/core/src/main/scala/cats/mtl/Tell.scala b/core/src/main/scala/cats/mtl/Tell.scala index b8df0cb1..f3d5fab2 100644 --- a/core/src/main/scala/cats/mtl/Tell.scala +++ b/core/src/main/scala/cats/mtl/Tell.scala @@ -49,6 +49,9 @@ trait Tell[F[_], -L] extends Serializable { def tuple[A](ta: (L, A)): F[A] = writer(ta._2, ta._1) def fromWriter[L2 <: L, A](wa: Writer[L2, A]): F[A] = tuple(wa.run) + + def fromWriterT[L2 <: L, A](wa: WriterT[F, L2, A])(implicit F: FlatMap[F]): F[A] = + F.flatMap(wa.run)(tuple(_)) } private[mtl] trait TellMonadPartialOrder[F[_], G[_], L] extends Tell[G, L] { From d12d72fb5ffd467923d566594ce884e5044896ae Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Fri, 19 Jan 2024 13:26:09 -0800 Subject: [PATCH 3/3] Add `from{Option,OptionT}` Co-authored-by: Igor Ramazanov --- core/src/main/scala/cats/mtl/Raise.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/scala/cats/mtl/Raise.scala b/core/src/main/scala/cats/mtl/Raise.scala index 11ca8d6c..659a1b39 100644 --- a/core/src/main/scala/cats/mtl/Raise.scala +++ b/core/src/main/scala/cats/mtl/Raise.scala @@ -86,6 +86,12 @@ trait Raise[F[_], -E] extends Serializable { def fromEitherT[E2 <: E, A](ea: EitherT[F, E2, A])(implicit F: Monad[F]): F[A] = F.flatMap(ea.value)(fromEither(_)) + def fromOption[E2 <: E, A](oa: Option[A])(e: => E2)(implicit F: Applicative[F]): F[A] = + oa.fold[F[A]](raise(e))(F.pure) + + def fromOptionT[E2 <: E, A](ota: OptionT[F, A])(e: => E2)(implicit F: Monad[F]): F[A] = + F.flatMap(ota.value)(oa => fromOption(oa)(e)) + } private[mtl] trait RaiseMonadPartialOrder[F[_], G[_], E] extends Raise[G, E] {