Coproducts

Coproducts and discriminated unions

shapeless has a Coproduct type, a generalization of Scala's Either to an arbitrary number of choices. Currently it exists primarily to support Generic (see the next section), but will be expanded analogously to HList in later releases. Currently Coproduct supports mapping, selection and unification

type ISB = Int :+: String :+: Boolean :+: CNil

val isb = Coproduct[ISB]("foo")
isb.select[Int] should be(res0)

isb.select[String] should be(res1)

Coproduct also supports mapping given a polymorphic function such as

object sizeM extends Poly1 {
  implicit def caseInt = at[Int](i => (i, i))
  implicit def caseString = at[String](s => (s, s.length))
  implicit def caseBoolean = at[Boolean](b => (b, 1))
}
val m = isb map sizeM

m.select[(String, Int)] should be(res0)

In the same way that adding labels To the elements of an HList gives us a record, adding labels to the elements of a Coproduct gives us a discriminated union.

import union._, syntax.singleton._

type U = Union.`'i -> Int, 's -> String, 'b -> Boolean`.T

val u = Coproduct[U](Symbol("s") ->> "foo") // Inject a String into the union at label 's

u.get(Symbol("i")) should be(res0)
u.get(Symbol("s")) should be(res1)
u.get(Symbol("b")) should be(res2)