If I have this:
case class Foo(
age: Int,
name: String,
bar: List[Bar],
alive: Boolean
)
case class Bar(
hey: String,
you: String
)
Can I create a lens that can get/set foo.bar(1).you
?
shapeless is a type class and dependent type based generic programming library for Scala.
A HList is a List where the type of every element is statically known at compile time. You may see them as "tuples on steroid". The beauty of HList compared to tuples is that you'll find all the essential List methods like take , head , tail , map , flatMap , zip , etc.
Not out of the box, and you really need a partial lens to look things up in a list by index responsibly. Scalaz provides what you need, though, and shapeless-contrib makes interoperability easy:
import scalaz.PLens._
import shapeless.lens
import shapeless.contrib.scalaz._
val secondBar = (lens[Foo] >> 'bar).asScalaz.partial.andThen(listNthPLens(1))
And then:
scala> secondBar.get(fooB)
res0: Option[Bar] = None
scala> secondBar.get(fooA)
res1: Option[Bar] = Some(Bar(foo,bar))
scala> secondBar.set(fooA, Bar("bar", "foo"))
res2: Option[Foo] = Some(Foo(1,,List(Bar(,), Bar(bar,foo)),false))
scala> secondBar.set(fooB, Bar("bar", "foo"))
res3: Option[Foo] = None
If you don't mind living dangerously, you could also write your own Shapeless lens for looking up locations in a list (with a type like Lens[List[A], A]
), but that would be giving up a lot of the value of both Shapeless and lenses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With