Shapeless で Scrap Your Boilerplate 実装を使用して一部のケース クラスを操作したいのですが、SYB コンビネータeverything
が type のフィールドをトラバースする方法を見つけようとして立ち往生していSeq[...]
ます。
たとえば、次のようなツリーを定義します。
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]
葉の数を数えるには、次のようにするとうまくいきます
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
ただし、Seq
フィールドの代わりに子を格納するためにa を使用する場合Node
case class Node[+A](children : Seq[Tree[A]]) extends Tree[A]
次にeverything
、フィールド children をトラバースできません:
scala> everything(countLeaves)(sum)(Node(Seq(Leaf(1), Leaf(2))))
res1: Int = 0
いろいろ試してみましたが、何もうまくいきませんでした。Data
forの正しいインスタンスを記述する方法もわかりませんでしたSeq[...]
。
UPDATE : fromのData
インスタンスを適応させるとうまくいくようですList
shapeless.Data
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
}