Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Shapeless 2.0.0 lens work with Lists/collections?

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?

like image 631
Greg Avatar asked Oct 23 '14 22:10

Greg


People also ask

What is shapeless Scala?

shapeless is a type class and dependent type based generic programming library for Scala.

What is HList?

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.


1 Answers

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.

like image 56
Travis Brown Avatar answered Sep 20 '22 10:09

Travis Brown