Last active
May 31, 2021 08:38
-
-
Save programaker/51c31e8c1ca3d4715b872d610c1a636c to your computer and use it in GitHub Desktop.
Scala 3 context functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cats.Monad | |
import cats.syntax.functor.* | |
import cats.effect.IO | |
import cats.effect.unsafe.implicits.global | |
case class Frunfles(id: Long, name: String) | |
trait DatabaseConnection: | |
def exec[F[_]: Monad](op: String): F[Unit] | |
object DatabaseConnection: | |
given DatabaseConnection with | |
def exec[F[_]: Monad](op: String): F[Unit] = Monad[F].pure(println(s">>> DB op = $op")) | |
// single-dependency "primitive" environments | |
type MonadEnv[F[_], A] = Monad[F] ?=> F[A] | |
type DatabaseEnv[A] = DatabaseConnection ?=> A | |
// composing envs by nesting | |
// both are equivalent! | |
type Env[F[_], A] = MonadEnv[F, DatabaseEnv[A]] | |
type Env2[F[_], A] = DatabaseEnv[MonadEnv[F, A]] | |
// multi-dependency environments | |
// both are equivalent! | |
type Env3[F[_], A] = (DatabaseConnection, Monad[F]) ?=> F[A] | |
type Env4[F[_], A] = (Monad[F], DatabaseConnection) ?=> F[A] | |
// need "Env" | |
def findAllFrunfles[F[_]]: Env[F, List[Frunfles]] = | |
summon[DatabaseConnection].exec("findAll").map(_ => List.empty) | |
def findFrunflesById[F[_]](id: Long): Env[F, Option[Frunfles]] = | |
summon[DatabaseConnection].exec("findById").map(_ => None) | |
// need "Env2" | |
def insertFrunfles[F[_]](f: Frunfles): Env2[F, Unit] = | |
summon[DatabaseConnection].exec("insert") | |
// need "Env3" | |
def updateFrunfles[F[_]](f: Frunfles): Env3[F, Unit] = | |
summon[DatabaseConnection].exec("update") | |
// need "Env4" | |
def deleteFrunfles[F[_]](id: Long): Env4[F, Unit] = | |
summon[DatabaseConnection].exec("delete") | |
// nesting order does not matter! | |
// parameter order does not matter! | |
// mixing different envs does not matter! | |
// the functions are called as if the envs don't exist at all! | |
val io: IO[Unit] = | |
for | |
_ <- insertFrunfles[IO](Frunfles(1L, "frunfles")) | |
_ <- findFrunflesById[IO](1L) | |
_ <- updateFrunfles[IO](Frunfles(1L, "sbrubbles")) | |
_ <- deleteFrunfles[IO](1L) | |
yield () | |
val res1 = io.unsafeRunSync() | |
val res2 = findAllFrunfles[IO].unsafeRunSync() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment