From efaf0f505439c0d803f95ffdb671c5dcd0008b0a Mon Sep 17 00:00:00 2001 From: Valeriy Avanesov Date: Sat, 18 Jul 2020 21:56:48 +0200 Subject: [PATCH 1/2] A method `StateT.fromState` turning `State[A, F[B]]` into `StateT[F, A, B]` is added. --- core/src/main/scala/cats/data/IndexedStateT.scala | 11 +++++++++++ .../test/scala/cats/tests/IndexedStateTSuite.scala | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/core/src/main/scala/cats/data/IndexedStateT.scala b/core/src/main/scala/cats/data/IndexedStateT.scala index c0cae4b8b6..bb36e6f295 100644 --- a/core/src/main/scala/cats/data/IndexedStateT.scala +++ b/core/src/main/scala/cats/data/IndexedStateT.scala @@ -199,6 +199,17 @@ private[data] trait CommonStateTConstructors { def get[F[_], S](implicit F: Applicative[F]): IndexedStateT[F, S, S, S] = IndexedStateT(s => F.pure((s, s))) + + /** + * Turn `State[A, F[B]]` into `StateT[F, A, B]` + */ + def fromState[F[_]: Applicative, A, B](s: State[A, F[B]]): StateT[F, A, B] = + s.transformF { eval => + import cats.implicits._ + + val (a, fb) = eval.value + fb.map((a, _)) + } } object IndexedStateT extends IndexedStateTInstances with CommonStateTConstructors0 { diff --git a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala b/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala index 71c5e1ded7..654008962a 100644 --- a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala +++ b/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala @@ -324,6 +324,17 @@ class IndexedStateTSuite extends CatsSuite { } } + test("fromState correctly turns State[A, F[B]] into StateT[F, A, B]") { + val state: State[Int, Option[Int]] = add1.map(Some.apply) + import cats.implicits.catsStdInstancesForOption + forAll { (initial: Int) => + StateT.fromState(state).run(initial).get should === { + val (s, Some(result)) = state.run(initial).value + (s, result) + } + } + } + implicit val iso: Isomorphisms[IndexedStateT[ListWrapper, String, Int, *]] = Isomorphisms.invariant[IndexedStateT[ListWrapper, String, Int, *]]( IndexedStateT.catsDataFunctorForIndexedStateT(ListWrapper.monad) From 7ff01565f4627eac81acea4e2d7d99d6c6d73b56 Mon Sep 17 00:00:00 2001 From: Valeriy Avanesov Date: Tue, 21 Jul 2020 12:25:32 +0200 Subject: [PATCH 2/2] Usage of Applicative typeclass is desugared in the method `StateT.fromState` for the sake of consistency with the rest of the file. --- core/src/main/scala/cats/data/IndexedStateT.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/main/scala/cats/data/IndexedStateT.scala b/core/src/main/scala/cats/data/IndexedStateT.scala index bb36e6f295..7f9c432f62 100644 --- a/core/src/main/scala/cats/data/IndexedStateT.scala +++ b/core/src/main/scala/cats/data/IndexedStateT.scala @@ -203,12 +203,10 @@ private[data] trait CommonStateTConstructors { /** * Turn `State[A, F[B]]` into `StateT[F, A, B]` */ - def fromState[F[_]: Applicative, A, B](s: State[A, F[B]]): StateT[F, A, B] = + def fromState[F[_], A, B](s: State[A, F[B]])(implicit F: Applicative[F]): StateT[F, A, B] = s.transformF { eval => - import cats.implicits._ - val (a, fb) = eval.value - fb.map((a, _)) + F.map(fb)((a, _)) } }