Skip to content

Instantly share code, notes, and snippets.

@kenbot
Created October 3, 2014 15:57
Show Gist options
  • Save kenbot/01162f53b343b62952f0 to your computer and use it in GitHub Desktop.
Save kenbot/01162f53b343b62952f0 to your computer and use it in GitHub Desktop.
Syntax sugar to effortlessly interoperate between Reader monads
case class has[Owner, A](get: Owner => A)
implicit def ownerHasPairs[Owner, A, B](implicit a: Owner has A, b: Owner has B): Owner has (A,B) =
has(owner => (a.get(owner), b.get(owner)))
implicit def pairHas1st[A,B]: (A,B) has A = has(_._1)
implicit def pairHas2nd[A,B]: (A,B) has B = has(_._2)
implicit def widenReaderToOwner[Owner, O, A](reader: Reader[O, A])(implicit ev: Owner has O): Reader[Owner, A] =
reader.local[Owner](implicitly[Owner has O].get)
// For custom classes:
case class Config(db: DB, cred: Cred, lang: Lang)
implicit val configHasDB: Config has DB = has(_.db)
implicit val configHasCred: Config has Cred = has(_.cred)
implicit val configHasLang: Config has Lang = has(_.lang)
// Each function can have minimal dependencies
// without an interoperability penalty or manually argument-passing
val dependsOnDB: Reader[DB, String] = ???
val dependsOnLang: Reader[Lang, String] = ???
val dependsOnCred: Reader[Cred, String] = ???
val dependsOnDBAndCred: Reader[(DB, Cred), String] = ???
def doConfigStuff: Reader[Config, String] = for {
a <- dependsOnDB
b <- dependsOnLang
c <- dependsOnDBAndCred
} yield List(a,b,c)
def doPairStuff: Reader[(Lang, Cred), String] = for {
a <- dependsOnLang
b <- dependsOnCred
} yield List(a,b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment