Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create cats IO monad from cats State

I am working with cats and I want to transform my val x: State[A, B] to StateT[IO, A, B]. Note: IO is from cats-effects.
How to do this elegantly?

like image 938
Mike Avatar asked Dec 23 '22 22:12

Mike


2 Answers

Try mapK in combination with cats.arrow.FunctionK.lift:

x.mapK(lift(IO.eval))

Full compilable code snippet:

import cats.effect.IO
import cats.data.{State, StateT}
import cats.arrow.FunctionK.lift

object InjectIdIO {
  def i[S, V](x: State[S, V]): StateT[IO, S, V] = x.mapK(lift(IO.eval))
}

This works because State[S, A] is actually StateT[Eval, S, A], and you want to replace the Eval by IO - this is what the mapK is usually for.


Another alternative with kind-projector:

x.mapK(Lambda[Eval ~> IO](IO.eval(_)))
like image 178
Andrey Tyukin Avatar answered Jan 12 '23 09:01

Andrey Tyukin


Try

def liftState[A, B](state: State[A, B]): StateT[IO, A, B] =
  StateT[IO, A, B] { s => IO.eval(state.run(s)) }

for example

val x: State[Int, String] = State(int => (int, "foo"))
liftState(x)
like image 20
Mario Galic Avatar answered Jan 12 '23 11:01

Mario Galic