Skip to content

Instantly share code, notes, and snippets.

@mmenestret
Last active February 28, 2019 15:47
Show Gist options
  • Save mmenestret/e40cb02dc76a6698b7dedee3d9d31f62 to your computer and use it in GitHub Desktop.
Save mmenestret/e40cb02dc76a6698b7dedee3d9d31f62 to your computer and use it in GitHub Desktop.
object EnvEffetWithoutSubtyping {
import EnvEffetWithoutSubtyping.Alg1.HasAlg1
import EnvEffetWithoutSubtyping.Alg2.HasAlg2
import EnvEffetWithoutSubtyping.Alg3.HasAlg3
trait Alg1
object Alg1 {
// Describe an env intersection type which contains an Alg1 type
trait HasAlg1[E] {
def alg1(e: E): Alg1
}
}
trait Alg2
object Alg2 {
trait HasAlg2[E] {
def alg2(e: E): Alg2
}
}
trait Alg3
object Alg3 {
trait HasAlg3[E] {
def alg3(e: E): Alg3
}
}
// Intersection types are case classes instead of mixed types
final case class SmallEnv(alg1: Alg1, alg2: Alg2)
object SmallEnv {
implicit val env1: HasAlg1[SmallEnv] = _.alg1
implicit val env2: HasAlg2[SmallEnv] = _.alg2
}
final case class BigEnv(alg1: Alg1, alg2: Alg2, alg3: Alg3)
object BigEnv {
// Define its HasX type classes, something to do with lenses here
implicit val env1: HasAlg1[BigEnv] = _.alg1
implicit val env2: HasAlg2[BigEnv] = _.alg2
implicit val env3: HasAlg3[BigEnv] = _.alg3
}
// No inference here
def program[Env: HasAlg1: HasAlg2: HasAlg3](): Reader[Env, Unit] = {
// Fine grained dependencies
def innerF1[E: HasAlg1]: Reader[E, Unit] = ???
def innerF2[E: HasAlg2]: Reader[E, Unit] = ???
def innerF3[E: HasAlg1: HasAlg2]: Reader[E, Unit] = ???
def innerF4[E: HasAlg1: HasAlg2: HasAlg3]: Reader[E, Unit] = ???
for {
_ <- innerF1 // Possible to thread Env here
_ <- innerF2
_ <- innerF3
_ <- innerF4
} yield ()
}
val env: BigEnv = ???
program[BigEnv].run(env)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment