I want to use the Scrap Your Boilerplate implementation in Shapeless to operate on some case classes but i'm stuck trying to figure out how to make the SYB combinator everything
traverse a field of type Seq[...]
.
For example, defining trees like:
abstract sealed class Tree[+A] extends Product with Serializable
case class Leaf[+A](value : A) extends Tree[A]
case class Node[+A](left : Tree[A], right : Tree[A]) extends Tree[A]
to count the number of leaves, the following works very well
object countLeaves extends Poly1 {
implicit def count[A] = at((a : Leaf[A]) => 1)
implicit def default[X] = at((x : X) => 0)
}
object sum extends Poly2 {
implicit final val add = at((i : Int, j : Int) => i + j)
}
scala> everything(countLeaves)(sum)(Node(Leaf(1), Leaf(2)))
res14: Int = 2
But when using a Seq
to store the children instead fields in Node
case class Node[+A](children : Seq[Tree[A]]) extends Tree[A]
then everything
is not able to traverse the field children :
scala> everything(countLeaves)(sum)(Node(Seq(Leaf(1), Leaf(2))))
res1: Int = 0
I tried various things but nothing worked. I did not figure out either how to write a correct instance of Data
for Seq[...]
.
UPDATE : Adapting the Data
instance for List
from shapeless.Data
seems to work out
implicit def seqData[P, T, R](implicit qt: Lazy[shapeless.poly.Case1.Aux[P, T, R]]): Data[P, Seq[T], R] =
new Data[P, Seq[T], R] {
def gmapQ(t: Seq[T]) = t.map(qt.value(_)).toList
}