Last active
October 12, 2017 08:54
-
-
Save danielkarch/a78458b659f22dd1a861062731c883be to your computer and use it in GitHub Desktop.
wiring an "application" with generic components
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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