Skip to content

Instantly share code, notes, and snippets.

@juanjovazquez
Last active September 27, 2016 10:45
Show Gist options
  • Select an option

  • Save juanjovazquez/0577e953f2056b4a77b536be99141ffa to your computer and use it in GitHub Desktop.

Select an option

Save juanjovazquez/0577e953f2056b4a77b536be99141ffa to your computer and use it in GitHub Desktop.
Approach for casting Any to Shapeless Coproduct
/*
* Copyright 2016 TECNOLOGIA, SISTEMAS Y APLICACIONES S.L.
*/
import org.scalatest.FunSuite
import shapeless.{ CNil, Coproduct, Inl, Inr, Typeable, :+: }
import shapeless.syntax.typeable.typeableOps
class AnyToCoproduct extends FunSuite with AnyToCoproductTypeableInstances {
case class Foo(id: String)
case class Bar(id: String)
case class Baz(id: String)
case class NotInCoproduct(id: String)
type Cop = Foo :+: Bar :+: Baz :+: CNil
test("types are cast only if they belong to the coproduct") {
val foo: Any = Foo("uuid_foo")
val bar: Any = Bar("uuid_bar")
val baz: Any = Baz("uuid_baz")
val notInCop: Any = NotInCoproduct("uuid_notInCop")
assert(foo.cast[Cop].isDefined)
assert(bar.cast[Cop].isDefined)
assert(baz.cast[Cop].isDefined)
assert(notInCop.cast[Cop].isEmpty)
}
}
trait AnyToCoproductTypeableInstances {
implicit def coproductTypeable[H, T <: Coproduct](
implicit castH: Typeable[H],
castT: Typeable[T]
): Typeable[H :+: T] =
new Typeable[H :+: T] {
def cast(t: Any): Option[H :+: T] = {
t.cast[Inl[H, T]] orElse t.cast[Inr[H, T]]
}
def describe = s"${ castH.describe } :+: ${ castT.describe }"
}
implicit def inlTypeable[H, T <: Coproduct](implicit castH: Typeable[H]): Typeable[Inl[H, T]] =
new Typeable[Inl[H, T]] {
def cast(t: Any): Option[Inl[H, T]] = {
if (t == null) None
else t.cast[H].map(Inl(_))
}
def describe: String = s"Inl[${ castH.describe }}]"
}
implicit def inrTypeable[H, T <: Coproduct](implicit castT: Typeable[T]): Typeable[Inr[H, T]] =
new Typeable[Inr[H, T]] {
def cast(t: Any): Option[Inr[H, T]] = {
if (t == null) None
else t.cast[T].map(Inr(_))
}
def describe = s"Inr[${ castT.describe }}]"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment