Skip to content

Instantly share code, notes, and snippets.

@julien-truffaut
Last active February 8, 2019 12:28
Show Gist options
  • Save julien-truffaut/78cc00b9ff5d4bb234e3 to your computer and use it in GitHub Desktop.
Save julien-truffaut/78cc00b9ff5d4bb234e3 to your computer and use it in GitHub Desktop.
Free Monad with nested Coproduct
package sandbox
import cats.data.Coproduct
import cats.free.{Free, Inject}
sealed trait Alg1[A]
sealed trait Alg2[A]
sealed trait Alg3[A]
class Alg1Ops[F[_]](implicit I: Inject[Alg1, F]){
def alg1: Free[F, Unit] = ???
}
class Alg2Ops[F[_]](implicit I: Inject[Alg2, F]){
def alg2: Free[F, Unit] = ???
}
class Alg3Ops[F[_]](implicit I: Inject[Alg3, F]){
def alg3: Free[F, Unit] = ???
}
object NestedCoproduct extends App {
type API[A] = Coproduct[Alg1, Coproduct[Alg2, Alg3, ?], A]
implicit def alg1Ops[F[_]](implicit I: Inject[Alg1, F]): Alg1Ops[F] = new Alg1Ops[F]()
implicit def alg2Ops[F[_]](implicit I: Inject[Alg2, F]): Alg2Ops[F] = new Alg2Ops[F]()
implicit def alg3Ops[F[_]](implicit I: Inject[Alg3, F]): Alg3Ops[F] = new Alg3Ops[F]()
// compile if uncommented
// Error:(40, 3) could not find implicit value for parameter A1: sandbox.Alg1Ops[sandbox.NestedCoproduct.API]
// program
// ^
// implicit val inject3a: Inject[Alg1, API] = implicitly
implicit val inject3b: Inject[Alg2, API] = implicitly
implicit val inject3c: Inject[Alg3, API] = implicitly
def program(implicit A1: Alg1Ops[API], A2: Alg2Ops[API], A3: Alg3Ops[API]): Free[API, Unit] =
for {
_ <- A1.alg1
_ <- A2.alg2
_ <- A3.alg3
} yield ()
program
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment