Skip to content

Instantly share code, notes, and snippets.

@djspiewak
Last active May 28, 2019 22:36
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 djspiewak/6cd3f9313dac7421f0afaab03fedb8fd to your computer and use it in GitHub Desktop.
Save djspiewak/6cd3f9313dac7421f0afaab03fedb8fd to your computer and use it in GitHub Desktop.
// ...get it?
final case class InductT[F[_], A](run: F[A])
// assume InductT is defined in some upstream library, so it knows nothing of the following
trait Functor[F[_]]
object Functor {
implicit def inductTFunctor[F[_]: Functor]: Functor[InductT[F, ?]] = new Functor[InductT[F, ?]]
}
// assume this is defined in the "enterprise-java-monads" library
trait Monad[F[_]] extends Functor[F[_]]
object Monad {
implicit def inductTMonad[F[_]: Monad]: Monad[InductT[F, ?]] = new Monad[InductT[F, ?]]
}
// and *this* is defined in "enterprise-java-traverses", which depends on "enterprise-java-functor" but not on the monad one
trait Traverse[F[_]] extends Functor[F]
object Traverse {
implicit def inductTTraverse[F[_]: Traverse]: Traverse[InductT[F, ?]] = new Traverse[InductT[F, ?]]
}
// finally, in a fifth library...
final case class Box[A](a: A)
object Box {
implicit object instance extends Monad[Box] with Traverse[Box]
}
// here's the call site
def foo[F[_]: Monad: Traverse] = implicitly[Functor[F]] // fails to compile!
def bar[F[_]](implicit F: Monad[F] with Traverse[F]) = implicitly[Functor[F]] // compiles!
bar[Box] // all good
bar[InductT[Box, ?]] // not so much
/**
* So to be clear, we have five independent compilation groups (i.e. separate libraries):
*
* 1. InductT
* 2. Functor (depends on InductT)
* 3. Monad (depends on Functor)
* 4. Traverse (depends on Functor)
* 5. Box/foo/bar (depends on Monad, Traverse)
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment