Skip to content

Instantly share code, notes, and snippets.

@channingwalton
Created May 19, 2014 09:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save channingwalton/2eaba6dd7a7533df5ba0 to your computer and use it in GitHub Desktop.
Save channingwalton/2eaba6dd7a7533df5ba0 to your computer and use it in GitHub Desktop.
Path-aware Lens
import scalaz._
object LensFu extends App {
case class FieldValue[T](name: String, v: T)
case class Field[T, F](name: String, lens: Lens[T, F]) {
def >=>[G](field: Field[F, G]): Field[T, G] = Field(name + "." + field.name, lens >=> field.lens)
def get(v: T): FieldValue[F] = FieldValue(name, lens.get(v))
def set(a: T, b: F): T = lens.set(a, b)
}
//// Model
case class Bar(fubar: String)
case class Foo(bar: Bar)
// Lenses
val barL: Lens[Foo, Bar] = Lens.lensu((b, j) ⇒ b.copy(bar = j), _.bar)
val fubarL: Lens[Bar, String] = Lens.lensu((b, j) ⇒ b.copy(fubar = j), _.fubar)
// Fields
val barField: Field[Foo, Bar] = Field("bar", barL)
val fubarField: Field[Bar, String] = Field("fubar", fubarL)
// compose fields
val fooBarFubar = barField >=> fubarField
// Example
val eg = Foo(Bar("woot"))
println(fooBarFubar.name) // bar.fubar
println(fooBarFubar.get(eg)) // FieldValue("bar.fubar", "woot")
// collections - um?
}
@channingwalton
Copy link
Author

Could shapeless records be better for this? Should the data types contained a NamedField[T](name: String, T) instead, but then how can ordinary lens be used to get the path?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment