Skip to content

Instantly share code, notes, and snippets.

@svalaskevicius
Last active September 19, 2019 06:39
Show Gist options
  • Save svalaskevicius/afe81d6c65b8aea9d87750eb9b9680f2 to your computer and use it in GitHub Desktop.
Save svalaskevicius/afe81d6c65b8aea9d87750eb9b9680f2 to your computer and use it in GitHub Desktop.
import cats.{Eval, Monad}
class StateT[F[_], S, A](val run: S => F[(S, A)]) extends AnyVal
object StateT {
implicit def monad[F[_], S](implicit F: Monad[F]): Monad[StateT[F, S, *]] = new Monad[StateT[F, S, *]] {
def flatMap[A, B](fa: StateT[F, S, A])(f: A => StateT[F, S, B]): StateT[F, S, B] =
new StateT(
s =>
F.flatMap(
F.flatMap(F.pure(s))(fa.run)
)(sa => f(sa._2).run(sa._1))
)
def tailRecM[A, B](a: A)(f: A => StateT[F, S, Either[A, B]]): StateT[F, S, B] = ???
def pure[A](x: A): StateT[F, S, A] = new StateT(s => F.pure((s, x)))
}
}
object Test {
def main(args: Array[String]) = {
val F = Monad[StateT[Eval, Unit, *]]
val unit = F.unit
val count = 20000
val resultL = (0 until count).foldLeft(unit) { (acc, _) =>
F.flatMap(acc)(_ => unit)
}
val resultR = (0 until count).foldLeft(unit) { (acc, _) =>
F.flatMap(unit)(_ => acc)
}
println(resultL.run(()).value)
println(resultR.run(()).value)
println("done")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment