Skip to content

Instantly share code, notes, and snippets.

@rubenpieters
Created January 27, 2017 06:21
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rubenpieters/d154975fac5d0ca36c3082e7d4bf2878 to your computer and use it in GitHub Desktop.
Save rubenpieters/d154975fac5d0ca36c3082e7d4bf2878 to your computer and use it in GitHub Desktop.
//-------------------------
// Monad Transformer
//-------------------------
import cats.data._
import cats.implicits._
import cats._
type MonadStackStateTEither[ErrorType, StateType, ReturnType] =
StateT[Either[ErrorType, ?], StateType, ReturnType]
def decrMonadStackStateTEither: MonadStackStateTEither[String, Int, Unit] = for {
x <- StateT.get[Either[String, ?], Int]
_ <- if (x > 0) { StateT.set[Either[String, ?], Int](x - 1) }
else { StateT.lift[Either[String, ?], Int, Unit](Left("error")) }
} yield ()
type MonadStackEitherTState[ErrorType, StateType, ReturnType] =
EitherT[State[StateType, ?], ErrorType, ReturnType]
def decrMonadStackEitherTState: MonadStackEitherTState[String, Int, Unit] = for {
x <- EitherT.liftT[State[Int, ?], String, Int](State.get[Int])
_ <- if (x > 0) { EitherT.liftT[State[Int, ?], String, Unit](State.set(x - 1)) }
else { EitherT.left[State[Int, ?], String, Unit](State.pure("error")) }
} yield ()
val resultStateTEither: Either[String, (Int, Unit)] = decrMonadStackStateTEither.run(0)
val resultEitherTState: (Int, Either[String, Unit]) = decrMonadStackEitherTState.value.run(0).value
println(resultStateTEither)
println(resultEitherTState)
//-------------------------
// mtl Monad Transformer
//-------------------------
// def decrMtlStateError[F[_]](implicit ms: MonadState[F, Int], me: MonadError[F, String]): F[Unit] = for {
// x <- ms.get
// _ <- if (x > 0) { ms.set(x - 1) }
// else { me.raiseError("error") }
// } yield ()
def decrMtlStateError[F[_]](implicit ms: MonadState[F, Int], me: MonadError[F, String]): F[Unit] = {
ms.flatMap(ms.get) { x =>
if (x > 0) { ms.set(x - 1) }
else { me.raiseError("error") }
}
}
implicit def monadStateEitherT[F[_], E, S](implicit ms: MonadState[F, S]): MonadState[EitherT[F, E, ?], S] = new MonadState[EitherT[F, E, ?], S] {
val F = Monad[F]
override def get: EitherT[F, E, S] = EitherT.liftT(ms.get)
override def set(s: S): EitherT[F, E, Unit] = EitherT.liftT(ms.set(s))
// copied from cats EitherTMonad
override def pure[A](a: A): EitherT[F, E, A] = EitherT(F.pure(Either.right(a)))
override def flatMap[A, B](fa: EitherT[F, E, A])(f: A => EitherT[F, E, B]): EitherT[F, E, B] = fa flatMap f
override def tailRecM[A, B](a: A)(f: A => EitherT[F, E, Either[A, B]]): EitherT[F, E, B] =
EitherT(F.tailRecM(a)(a0 => F.map(f(a0).value) {
case Left(l) => Right(Left(l))
case Right(Left(a1)) => Left(a1)
case Right(Right(b)) => Right(Right(b))
}))
}
val resultMtlStateTEither: Either[String, (Int, Unit)] = decrMtlStateError[StateT[Either[String, ?], Int, ?]].run(0)
val resultMtlEitherTState: (Int, Either[String, Unit]) = decrMtlStateError[EitherT[State[Int, ?], String, ?]].value.run(0).value
println(resultMtlStateTEither)
println(resultMtlEitherTState)
//-------------------------
// Eff
//-------------------------
import org.atnos.eff._
import org.atnos.eff.all._
import org.atnos.eff.syntax.all._
type _eitherString[R] = Either[String, ?] |= R
type _stateInt[R] = State[Int, ?] |= R
def decrEff[R : _eitherString : _stateInt]: Eff[R, Unit] = for {
x <- get
_ <- if (x > 0) { put(x - 1) }
else { left("error") }
} yield ()
type FxStack = Fx.fx2[State[Int, ?], Either[String, ?]]
val resultRunStateRunEither: Either[String, (Unit, Int)] = decrEff[FxStack].runState(0).runEither.run
val resultRunEitherRunState: (Either[String, Unit], Int) = decrEff[FxStack].runEither.runState(0).run
println(resultRunStateRunEither)
println(resultRunEitherRunState)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment