tofu.Context.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tofu-core_2.11 Show documentation
Show all versions of tofu-core_2.11 Show documentation
Opinionated Set of tool for functional programming in scala
The newest version!
package tofu
import cats.{Applicative, Functor, Monad}
import cats.data.ReaderT
import tofu.optics.{Contains, Equivalent, Extract}
/** lightweight version of ApplicativeAsk */
trait Context[F[_]] {
def functor: Functor[F]
type Ctx
def context: F[Ctx]
def ask[A](f: Ctx => A): F[A] = functor.map(context)(f)
def askF[A](f: Ctx => F[A])(implicit F: Monad[F]): F[A] = F.flatMap(context)(f)
def extract[A](extr: Extract[Ctx, A]): HasContext[F, A] = new ContextExtractInstance[F, Ctx, A](this, extr)
}
object Context extends ContextInstances {
def apply[F[_]](implicit ctx: Context[F]): Aux[F, ctx.Ctx] = ctx
type Aux[F[_], C] = Context[F] { type Ctx = C }
}
trait ContextInstances extends LocalInstances[HasContext]
trait Local[F[_]] extends Context[F] {
def local[A](fa: F[A])(project: Ctx => Ctx): F[A]
def subcontext[A](contains: Ctx Contains A): HasLocal[F, A] = new LocalContainsInstance[F, Ctx, A](this, contains)
}
object Local extends LocalInstances[HasLocal] {
def apply[F[_]](implicit ctx: Local[F]): HasLocal[F, ctx.Ctx] = ctx
type Aux[F[_], C] = HasLocal[F, C]
}
trait LocalInstances[TCA[f[_], r] >: HasLocal[f, r]] extends RunContextInstances[TCA]
trait RunContext[F[_]] extends Local[F] {
type Lower[A]
def runContext[A](fa: F[A])(ctx: Ctx): Lower[A]
def runEquivalent[A](eq: Equivalent[Ctx, A]): RunContext.Aux[F, Lower, A] =
new RunContextEquivalentInstance[F, Lower, Ctx, A](this, eq)
}
object RunContext extends RunContextInstances[HasContextRun] {
def apply[F[_]](implicit ctx: RunContext[F]): Aux[F, ctx.Lower, ctx.Ctx] = ctx
type Aux[F[_], G[_], C] = RunContext[F] {
type Lower[A] = G[A]
type Ctx = C
}
}
trait RunContextInstances[TCA[f[_], r] >: HasContextRun[f, r]] {
implicit def readerTContext[C, F[_]: Applicative]: TCA[ReaderT[F, C, *], C] = new RunContext[ReaderT[F, C, *]] {
type Lower[A] = F[A]
type Ctx = C
override def runContext[A](fa: ReaderT[F, C, A])(ctx: C): F[A] = fa.run(ctx)
override def local[A](fa: ReaderT[F, C, A])(project: C => C): ReaderT[F, C, A] = fa.local(project)
val functor: Functor[ReaderT[F, C, *]] = Functor[ReaderT[F, C, *]]
def context: ReaderT[F, C, C] = ReaderT.ask[F, C]
}
}
private[tofu] class ContextExtractInstance[F[_], C1, C2](ctx: F HasContext C1, extract: C1 Extract C2)
extends Context[F] {
type Ctx = C2
def functor: Functor[F] = ctx.functor
def context: F[C2] = functor.map(ctx.context)(extract.extract)
}
private[tofu] class LocalContainsInstance[F[_], C1, C2](ctx: F HasLocal C1, contains: C1 Contains C2)
extends ContextExtractInstance[F, C1, C2](ctx, contains) with Local[F] {
def local[A](fa: F[A])(project: C2 => C2): F[A] = ctx.local(fa)(contains.update(_, project))
}
private[tofu] class RunContextEquivalentInstance[F[_], G[_], C1, C2](
ctx: RunContext.Aux[F, G, C1],
equivalent: C1 Equivalent C2
) extends LocalContainsInstance[F, C1, C2](ctx, equivalent) with RunContext[F] {
type Lower[a] = G[a]
def runContext[A](fa: F[A])(c: C2): G[A] = ctx.runContext(fa)(equivalent.upcast(c))
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy