I'm trying to use shapeless to create a poly2 function that can take a coproduct:
case class IndexedItem(
item1: Item1,
item2: Item2,
item3: Item3
)
case class Item1(name: Int)
case class Item2()
case class Item3()
object IndexUpdater {
type Indexable = Item1 :+: Item2 :+: Item3 :+: CNil
object updateCopy extends Poly2 {
implicit def caseItem1 = at[IndexedItem, Item1] { (a, b) => a.copy(item1 = b) }
implicit def caseItem2 = at[IndexedItem, Item2] { (a, b) => a.copy(item2 = b) }
implicit def caseItem3 = at[IndexedItem, Item3] { (a, b) => a.copy(item3 = b) }
}
def mergeWithExisting(existing: IndexedItem, item: Indexable): IndexedItem = {
updateCopy(existing, item)
}
}
This gives me an error of
Error:(48, 15) could not find implicit value for parameter cse: shapeless.poly.Case[samples.IndexUpdater.updateCopy.type,shapeless.::[samples.IndexedItem,shapeless.::[samples.IndexUpdater.Indexable,shapeless.HNil]]] updateCopy(existing, item)
Which I think makes sense given that the Poly2 is working on instances of the items, and not the expanded coproduct type (i.e. the implicits are generated for Item1 and not Indexable)
However, if I don't apply the poly2 with the PolyApply overload, and instead do:
def mergeWithExisting(existing: IndexedItem, item: Indexable): IndexedItem = {
item.foldLeft(existing)(updateCopy)
}
Then it does work. I'm not sure what the foldleft is doing such that the types resolve. If this is the accepted way the how do I make this generic such that I can use a Poly3? or Poly4?
Is there any way to widen the type in the poly to get this to work with the apply method? Maybe I'm going about this the wrong way, I'm open to suggestions