I read the following about coproducts in the excellent Shapeless Guide:
... it’s worth stating that Coproducts aren’t particularly special. The functionality above can be achieved using Either and Nothing in place of :+: and CNil.
Here's the above code:
import shapeless.{Coproduct, :+:, CNil, Inl, Inr}
case class Red()
case class Amber()
case class Green()
type Light = Red :+: Amber :+: Green :+: CNil
val red: Light = Inl(Red())
// red: Light = Inl(Red())
val green: Light = Inr(Inr(Inl(Green())))
// green: Light = Inr(Inr(Inl(Green())))
For my own understanding, what is the benefit, if any, of using a Coproduct over a sealed trait
?
One benefit is similar to that of using type classes rather than inheritance: ad-hoc polymorphism. You can make a Coproduct out of any types, even those outside of your control, e.g. String and Int. You can't do that with a sealed trait (unless you made awkward StringHolder
and IntHolder
case classes to wrap them).
Same as the benefit of using HList
over a case class
: you can write generic code which works for all coproducts, or all coproducts which satisfy some condition. And then use Generic
to make the same code work with sealed trait
s as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With