Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Shapeless autolifting Kleisli#local to avoid lambda boilerplate
import cats._
import cats.data._
import shapeless._
import shapeless.ops.hlist.Selector
implicit class ReaderOps[A, B, L <: HList](f: Reader[A, B]) {
def liftD[AA](implicit ga: Generic.Aux[AA, L], sel: Selector[L, A]): Reader[AA, B] =
f.local[AA](aa => sel.apply(ga.to(aa)))
}
case class Dep1(msg: String)
case class Dep2(amount: Int)
case class Config(dep: Dep1, dep2: Dep2)
implicit val module: Config = Config(Dep1("It's a : "), Dep2(10))
def service1: Reader[Dep1, String] = Reader { d1: Dep1 => d1.msg }
def service2: Reader[Dep2, Int] = Reader { d2: Dep2 => d2.amount }
val composed = for {
a <- service1.liftD[Config] // no need to provide local manual boilerplate
b <- service2.liftD[Config]
} yield a + b
composed.run(module)
// res0: cats.Id[String] = It's a : 10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.