Skip to content

Instantly share code, notes, and snippets.

@danielkarch
Last active October 12, 2017 08:54
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 danielkarch/a78458b659f22dd1a861062731c883be to your computer and use it in GitHub Desktop.
Save danielkarch/a78458b659f22dd1a861062731c883be to your computer and use it in GitHub Desktop.
wiring an "application" with generic components
package grafterexample
import cats.data.Reader
import org.zalando.grafter.GenericReader.widenReader
case class Config()
object Application extends App {
val x: Wants[Int] = Wants.reader[Config, Int].apply(Config())
println(x.get)
}
trait Wants[T] { def get: T }
object Wants {
implicit def reader[A, T](implicit implReader: Reader[A, WantsImpl[T]]): Reader[A, Wants[T]] =
implReader
}
trait Provides[T] { def value: T }
object Provides {
implicit def reader[A]: Reader[A, Provides[Int]] =
ProvidesInt.reader[A]
}
// Generic; only uses the provider to do its thing.
case class WantsImpl[T](provider: Provides[T]) extends Wants[T] {
def get: T = provider.value
}
object WantsImpl {
implicit def reader[A, T](implicit providesReader: Reader[A, Provides[T]]): Reader[A, WantsImpl[T]] =
providesReader.map(WantsImpl.apply)
}
// Non-generic; the provider needs to actually know the type of the thing it provides.
case class ProvidesInt(i: Int) extends Provides[Int] {
def value: Int = i
}
object ProvidesInt {
implicit def reader[A]: Reader[A, Provides[Int]] =
Reader(_ => ProvidesInt(7))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment