Skip to content

Instantly share code, notes, and snippets.

@ShahOdin
Last active April 14, 2020 13:26
Show Gist options
  • Save ShahOdin/799f6ec2f43f2fad72fce604e7668ecd to your computer and use it in GitHub Desktop.
Save ShahOdin/799f6ec2f43f2fad72fce604e7668ecd to your computer and use it in GitHub Desktop.
A demo of dependencies injection
case class Config(barConfig: Config.BarConfig, fooConfig: Config.FooConfig)
object Config {
trait BarConfig
trait FooConfig
}
/* Client layer */
import cats.data.ReaderT
import Config._
trait BarClient[F[_]]
object BarClient{
def readerT[F[_]]: ReaderT[F, Config, BarClient[F]] = readerT_.local(_.barConfig)
private def readerT_[F[_]]: ReaderT[F, BarConfig, BarClient[F]] = ???
}
trait FooClient[F[_]]
object FooClient{
def readerT[F[_]]: ReaderT[F, Config, FooClient[F]] = readerT_.local(_.fooConfig)
private def readerT_[F[_]]: ReaderT[F, FooConfig, FooClient[F]] = ???
}
/* Logic layer */
import cats.Monad
import cats.syntax.semigroupal._
trait BazHandler[F[_]]
object BazHandler{
def readerT[F[_]: Monad]: ReaderT[F, Config, BazHandler[F]] = {
FooClient.readerT[F].product(BarClient.readerT[F])
.andThen(readerT_[F])
}
private def readerT_[F[_]]: ReaderT[F, (FooClient[F], BarClient[F]), BazHandler[F]] = ???
}
trait QuxHandler[F[_]]
object QuxHandler{
def readerT[F[_]: Monad]: ReaderT[F, Config, QuxHandler[F]] = {
FooClient.readerT[F].product(BarClient.readerT[F])
.andThen(readerT_[F])
}
private def readerT_[F[_]]: ReaderT[F, (FooClient[F], BarClient[F]), QuxHandler[F]] = ???
}
case class ServiceDependencies[F[_]](bazHandler: BazHandler[F], quxHandler: QuxHandler[F])
object ServiceDependencies{
def readerT[F[_]: Monad]: ReaderT[F, Config, ServiceDependencies[F]] = for {
baz <- BazHandler.readerT[F]
qux <- QuxHandler.readerT[F]
} yield ServiceDependencies[F](baz, qux)
}
/* Service layer: publishers, routers, consumers */
import cats.syntax.functor._
import cats.effect.{IO, IOApp, ExitCode}
import fs2.Stream
object App extends IOApp {
val config: Config = ???
def stream: Stream[IO, Unit] = for {
_ <- Stream.eval(ServiceDependencies.readerT[IO].run(config))
} yield ()
override def run(args: List[String]): IO[ExitCode] = stream.compile.drain.as(ExitCode.Success)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment