Skip to content

Instantly share code, notes, and snippets.

@maxkorolev
Last active July 4, 2019 13:40
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 maxkorolev/afa3056b784cc3ad10a1d14a047d012d to your computer and use it in GitHub Desktop.
Save maxkorolev/afa3056b784cc3ad10a1d14a047d012d to your computer and use it in GitHub Desktop.
ZIO environment usage
// simple programm to show how to use ZIO and to show which opportunities it can bring
import zio._
// trait to describe Config
trait HasConfig {
def dbConfig: DBConfig
def loggerConfig: LoggerConfig
}
case class DBConfig(db: String)
case class LoggerConfig(logColor: String)
def dbConfig = ZIO.access[HasConfig](_.dbConfig)
def loggerConfig = ZIO.access[HasConfig](_.loggerConfig)
// module
trait Logger {
val logger: Logger.Service
}
// service interface
object Logger {
trait Service {
// requirement: There must be HasConfig in the context
def log(value: Int): ZIO[HasConfig, Throwable, Unit]
}
}
// service implementation
trait LoggerServiceLive extends Logger {
val logger: Logger.Service = new Logger.Service {
def log(value: Int): ZIO[HasConfig, Throwable, Unit] =
for {
// access to loggerConfig
c <- loggerConfig
_ <- ZIO.effect {
println(s"$RESET${c.logColor}$value$RESET")
}
} yield ()
}
}
// easy access to service
def log(value: Int): ZIO[Logger with HasConfig, Throwable, Unit] =
ZIO.accessM(_.logger log value)
// module
trait Repo {
val repo: Repo.Service
}
// service interface
object Repo {
trait Service {
// requirement: There must be Logger and HasConfig in the context
def get(id: Int): ZIO[Logger with HasConfig, Throwable, Int]
}
}
// service implementation
trait RepoServiceLive extends Repo {
val repo: Repo.Service = new Repo.Service {
def get(id: Int): ZIO[Logger with HasConfig, Throwable, Int] =
for {
// access to db config if it needs, here is just a showcase
_ <- dbConfig
// use log
_ <- log(id)
} yield id
}
}
// easy access to service
def get(id: Int): ZIO[Repo with Logger with HasConfig, Throwable, Int] =
ZIO.accessM(_.repo get id)
// main programm
val program = for {
// you are writing programm in imperative and simple to read style,
// but with functional and typesafe approach in the heart
a <- get(123)
b <- get(123)
s = a + b
_ <- log(s)
} yield s
type AppEnv = Repo with Logger with HasConfig
// you must provide implementations as a context
val r = program.provide(
new RepoServiceLive with LoggerServiceLive with HasConfig {
def dbConfig: DBConfig = DBConfig("")
def loggerConfig: LoggerConfig = LoggerConfig(GREEN)
}
)
val runtime = new DefaultRuntime {}
// and run it
runtime.unsafeRun(r) must beEqualTo(246)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment