Skip to content

Instantly share code, notes, and snippets.

@LukaJCB
Last active June 29, 2018 14:52
Show Gist options
  • Save LukaJCB/3a24b17d4bfce642c939e0a45512c2c0 to your computer and use it in GitHub Desktop.
Save LukaJCB/3a24b17d4bfce642c939e0a45512c2c0 to your computer and use it in GitHub Desktop.
Easy monad transformer lifting?
trait MonadTrans[T[_[_], _]] {
def lift[M[_]: Monad, A](ma: M[A]): T[M, A]
def hoist[M[_]: Monad, N[_]: Monad, A](tma: T[M, A])(f: M ~> N): T[N, A]
}
object MonadTrans {
def apply[T[_[_], _]: MonadTrans]: MonadTrans[T] = implicitly
}
implicit def applicativeAskMonadTrans[T[_[_], _]: MonadTrans, M[_]: Monad, R]
(implicit T: Monad[T[M, ?]], A: ApplicativeAsk[M, R]): ApplicativeAsk[T[M, ?], R] = new DefaultApplicativeAsk[T[M, ?], R] {
val applicative: Applicative[T[M, ?]] = T
def ask: T[M, R] = MonadTrans[T].lift(A.ask)
}
implicit def monadTransForOptionT: MonadTrans[OptionT] = new MonadTrans[OptionT] {
def lift[M[_]: Monad, A](ma: M[A]): OptionT[M, A] = OptionT.liftF(ma)
def hoist[M[_]: Monad, N[_] : Monad, A](tma: OptionT[M, A])(f: M ~> N): OptionT[N, A] = tma.mapK(f)
}
def foo[F[_]](implicit F: ApplicativeAsk[F, Int]): F[Int] =
F.applicative.map(F.ask)(_ + 1)
val result: Int =
foo[OptionT[Kleisli[Eval, Int, ?], ?]].value.run(42).value.getOrElse(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment