Given:
case class Foo(a: Option[Int], b: Option[Int], c: Option[Int], d: Option[Int])
I'd like to only allow constructing a Foo
only if at least one of its arguments is Some
, i.e. not all fields are None
.
It would be quite a bit of code to write an Algebraic Data Type, and then make sub-classes for each variant:
sealed trait Foo
case class HasAOnly(a: Int) extends Foo
case class HasAB(a: Int, b: Int) extends Foo
// etc...
Is there a cleaner, i.e. less code, way to address my problem using shapeless
?
Thanks to the sealed abstract case class
trick which Rob Norris recently publicised, you can keep the characteristics of your Foo
case class but also provide your own smart constructor which returns an Option[Foo]
depending on whether the given arguments pass all your criteria or not:
sealed abstract case class Foo(
a: Option[Int], b: Option[Int], c: Option[Int], d: Option[Int])
object Foo {
private class Impl(
a: Option[Int], b: Option[Int], c: Option[Int], d: Option[Int])
extends Foo(a, b, c, d)
def apply(
a: Option[Int],
b: Option[Int],
c: Option[Int],
d: Option[Int]): Option[Foo] =
(a, b, c, d) match {
case (None, None, None, None) => None
case _ => Some(new Impl(a, b, c, d))
}
}