I have two instantiated case classes of the same type.
case class Foo(x : Option[String], y : Option[String], z : Option[String])
Lets cal
As discusssed in this thread, this is how you can solve the problem with shapeless, in a completely type-safe manner.
scala> import shapeless._
import shapeless._
scala> import HList._
import HList._
scala> case class Foo(a: Option[Int], b: Option[Int])
defined class Foo
scala> val a = Foo(Some(3), None)
a: Foo = Foo(Some(3),None)
scala> val b = Foo(Some(22), Some(1))
b: Foo = Foo(Some(22),Some(1))
scala> implicit val fooIso = HListIso(Foo.apply _, Foo.unapply _)
fooIso: shapeless.HListIso[Foo,shapeless.::[Option[Int],shapeless.::[Option[Int],shapeless.HNil]]] = shapeless.HListIso@11c5b77
scala> type O2[+A] = (Option[A], Option[A])
defined type alias O2
scala> object mapper extends (O2 ~> Option) {
| def apply[A](x: O2[A]): Option[A] = x._1.orElse(x._2)
| }
defined module mapper
scala> fooIso.fromHList(fooIso.toHList(a).zip(fooIso.toHList(b)).map(mapper))
res13: Foo = Foo(Some(3),Some(1))