|
| 1 | +package zipper |
| 2 | + |
| 3 | +import contrib.shapeless3.{Replacer, Selector} |
| 4 | +import shapeless3.deriving.K0 |
| 5 | +import shapeless3.deriving.K0.* |
| 6 | + |
| 7 | +import scala.collection.Factory |
| 8 | + |
| 9 | +private[zipper] trait ForImpl { |
| 10 | + given unzipListBased[A, L <: Tuple](using |
| 11 | + generic: K0.ProductGeneric[A] { type MirroredElemTypes = L }, |
| 12 | + selector: Selector[L, List[A]], |
| 13 | + replacer: Replacer.Aux[L, List[A], List[A], (List[A], L)] |
| 14 | + ): Unzip[A] with { |
| 15 | + def unzip(node: A): List[A] = selector(generic.toRepr(node)) |
| 16 | + def zip(node: A, children: List[A]): A = { |
| 17 | + val repr = replacer(generic.toRepr(node), children) |
| 18 | + generic.fromRepr(repr._2) |
| 19 | + } |
| 20 | + } |
| 21 | + |
| 22 | + class For[A, Coll[X] <: Seq[X]]: |
| 23 | + /** Derive an instance of `Unzip[A]` */ |
| 24 | + inline given derive[L <: Tuple](using |
| 25 | + generic: K0.ProductGeneric[A] { type MirroredElemTypes = L }, |
| 26 | + selector: Selector[L, Coll[A]], |
| 27 | + replacer: Replacer.Aux[L, Coll[A], Coll[A], (Coll[A], L)], |
| 28 | + factory: Factory[A, Coll[A]] |
| 29 | + ): Unzip[A] with { |
| 30 | + def unzip(node: A): List[A] = selector(generic.toRepr(node)).toList |
| 31 | + def zip(node: A, children: List[A]): A = { |
| 32 | + val repr = replacer(generic.toRepr(node), children.to(factory)) |
| 33 | + generic.fromRepr(repr._2) |
| 34 | + } |
| 35 | + } |
| 36 | + |
| 37 | + object For: |
| 38 | + /** |
| 39 | + * @tparam A The type of the tree-like data structure |
| 40 | + * @tparam Coll The type of the collection used for recursion (e.g. Vector) |
| 41 | + */ |
| 42 | + def apply[A, Coll[X] <: Seq[X]]: For[A, Coll] = new For[A, Coll] |
| 43 | +} |
0 commit comments