scala - shapeless convert case class to HList and skip all option fields -
i have next class:
case class foo(a: option[int], b: option[string], c: option[double])
as can see, fields optional, want convert class hlist or tuple, like
val f1 = foo(some(1) , none, some(3d)) val f2 = foo(none, "foo") val result1 = f1.to[int::double::hnil] // => 1::3d val result2 = f2.to[string::hnil] // "foo"
is possible, without reflection?
it might possible existing type classes in shapeless (something nattrel
, removeall
), i'm not 100% sure of that, , case i'd write own type class:
import shapeless._ trait optionalpieces[l <: hlist, s <: hlist] { def apply(l: l): option[s] } object optionalpieces extends lowpriorityoptionalpieces { implicit val hniloptionalpieces: optionalpieces[hnil, hnil] = new optionalpieces[hnil, hnil] { def apply(l: hnil): option[hnil] = some(hnil) } implicit def hconsoptionalpiecesmatch[h, t <: hlist, s <: hlist](implicit opt: optionalpieces[t, s] ): optionalpieces[option[h] :: t, h :: s] = new optionalpieces[option[h] :: t, h :: s] { def apply(l: option[h] :: t): option[h :: s] = { h <- l.head t <- opt(l.tail) } yield h :: t } } sealed class lowpriorityoptionalpieces { implicit def hconsoptionalpiecesnomatch[h, t <: hlist, s <: hlist](implicit opt: optionalpieces[t, s] ): optionalpieces[option[h] :: t, s] = new optionalpieces[option[h] :: t, s] { def apply(l: option[h] :: t): option[s] = opt(l.tail) } }
this witnesses l
contains at least of elements of s
wrapped in option
, in order, , gives way unwrap them @ runtime (safely).
we can define syntax helper class this:
implicit class optionalpiecessyntax[a, r <: hlist](a: a)(implicit gen: generic.aux[a, r] ) { def to[s <: hlist](implicit op: optionalpieces[gen.repr, s]): option[s] = op(gen.to(a)) }
and then:
scala> val f1 = foo(some(1) , none, some(3d)) f1: foo = foo(some(1),none,some(3.0)) scala> val f2 = foo(none, some("foo"), none) f2: foo = foo(none,some(foo),none) scala> val result1 = f1.to[int :: double :: hnil] result1: option[shapeless.::[int,shapeless.::[double,shapeless.hnil]]] = some(1 :: 3.0 :: hnil) scala> val result2 = f2.to[string :: hnil] result2: option[shapeless.::[string,shapeless.hnil]] = some(foo :: hnil)
if wanted exceptions, call .get
in syntax class, seems bad idea.
Comments
Post a Comment