Skip to content

Instantly share code, notes, and snippets.

@Tvaroh
Last active August 31, 2018 09:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tvaroh/efa364074626ba051dc048ae3a53fb8b to your computer and use it in GitHub Desktop.
Save Tvaroh/efa364074626ba051dc048ae3a53fb8b to your computer and use it in GitHub Desktop.
import cats.data.ReaderT
import cats.implicits._
import cats.{Applicative, Functor}
trait ContextRead[F[_], Ctx] {
def read: F[Ctx]
}
object ContextRead {
def apply[F[_], Ctx](implicit context: ContextRead[F, Ctx]): ContextRead[F, Ctx] = implicitly
def reader[F[_]: Applicative, Ctx]: ContextRead[ReaderT[F, Ctx, ?], Ctx] = new ReaderContextRead
private class ReaderContextRead[F[_]: Applicative, Ctx] extends ContextRead[ReaderT[F, Ctx, ?], Ctx] {
override def read: ReaderT[F, Ctx, Ctx] =
ReaderT.ask[F, Ctx]
}
implicit def functorInstance[F[_]: Functor, Ctx]: Functor[ContextRead[F, ?]] = new ContextReadFunctor
private class ContextReadFunctor[F[_]: Functor, Ctx] extends Functor[ContextRead[F, ?]] {
override def map[A, B](fa: ContextRead[F, A])(f: A => B): ContextRead[F, B] =
new ContextRead[F, B] {
override def read: F[B] = fa.read.map(f)
}
}
}
trait ContextScope[F[_], Ctx] {
def scope[T](f: Ctx => Ctx)(ft: F[T]): F[T]
}
object ContextScope {
def apply[F[_], Ctx](implicit context: ContextScope[F, Ctx]): ContextScope[F, Ctx] = implicitly
def reader[F[_]: Applicative, Ctx]: ContextScope[ReaderT[F, Ctx, ?], Ctx] = new ReaderContextScope
private class ReaderContextScope[F[_]: Applicative, Ctx] extends ContextScope[ReaderT[F, Ctx, ?], Ctx] {
override def scope[T](f: Ctx => Ctx)(ft: ReaderT[F, Ctx, T]): ReaderT[F, Ctx, T] =
ReaderT.local(f)(ft)
}
}
trait Context[F[_], Ctx] extends ContextRead[F, Ctx] with ContextScope[F, Ctx]
object Context {
def apply[F[_], Ctx](implicit context: Context[F, Ctx]): Context[F, Ctx] = implicitly
def reader[F[_]: Applicative, Ctx]: Context[ReaderT[F, Ctx, ?], Ctx] = new ReaderContext
private class ReaderContext[F[_]: Applicative, Ctx] extends Context[ReaderT[F, Ctx, ?], Ctx] {
override def read: ReaderT[F, Ctx, Ctx] =
contextRead.read
override def scope[T](f: Ctx => Ctx)(ft: ReaderT[F, Ctx, T]): ReaderT[F, Ctx, T] =
contextScope.scope(f)(ft)
private val contextRead = ContextRead.reader[F, Ctx]
private val contextScope = ContextScope.reader[F, Ctx]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment