Reactormonk
Reactormonk

Reputation: 21690

Recursively transform elements in shapeless records based on type

How would I recursively apply a Poly1 on a Record? I've been pointed at everywhere, but that doesn't seem to work well with Records.

object f extends Poly1 { implicit def atFoo = at[Foo](x => x) }
sealed trait Foo
case class Foo1(foo: Foo) extends Foo
case class Foo2(int: Int) extends Foo
def m = {
  val generic = LabelledGeneric[Foo]
  generic.from(everywhere(f)(generic.to(Foo1(Foo1(Foo2(3))))))
}

Gives me

[error]  found   : generic.Repr
[error]     (which expands to)  shapeless.:+:[Main.Foo1 with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("Foo1")],Main.Foo1],shapeless.:+:[Main.Foo2 with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("Foo2")],Main.Foo2],shapeless.CNil]]
[error]  required: shapeless.poly.Case[_1.type,shapeless.HNil]{type Result = ?} where val _1: shapeless.EverywhereAux[Main.f.type]
[error]     generic.from(everywhere(f)(generic.to(Foo1(Foo1(Foo2(3))))))
[error]                                          ^

http://scastie.org/16713

Upvotes: 3

Views: 294

Answers (1)

jdprc06
jdprc06

Reputation: 360

You don't need to call LabelledGeneric directly when using everywhere. It's handling the HList conversions for you, so you would call it instead like everywhere(f)(Foo1(Foo1(Foo2(3)))). I changed it to modify the Int field so you can clearly see it working:

import shapeless._

object f extends Poly1 {
  implicit def atFoo = at[Int](_ * 2)
}

sealed trait Foo
case class Foo1(foo: Foo) extends Foo
case class Foo2(int: Int) extends Foo

println(everywhere(f)(Foo1(Foo1(Foo2(3)))))

Upvotes: 1

Related Questions