Skip to content

Instantly share code, notes, and snippets.

@drostron
Created July 16, 2013 17:36
Show Gist options
  • Select an option

  • Save drostron/6010857 to your computer and use it in GitHub Desktop.

Select an option

Save drostron/6010857 to your computer and use it in GitHub Desktop.
a translation of the shapeless lens example to scalaz, https://github.com/milessabin/shapeless
import scalaz.Lens
object FocusOnScalaz {
// A pair of ordinary case classes ...
case class Address(street : String, city : String, postcode : String)
case class Person(name : String, age : Int, address : Address)
// Some lenses over Person/Address ...
val nameLens = Lens.lensu[Person, String]((u, newName) => u.copy(name = newName), _.name)
val ageLens = Lens.lensu[Person, Int]((u, newAge) => u.copy(age = newAge), _.age)
val addressLens = Lens.lensu[Person, Address]((u, newAddress) => u.copy(address = newAddress), _.address)
val addrStreetLens = Lens.lensu[Address, String]((u, newStreet) => u.copy(street = newStreet), _.street)
val addrCityLens = Lens.lensu[Address, String]((u, newCity) => u.copy(city = newCity), _.city)
val addrPostcodeLens = Lens.lensu[Address, String]((u, newCity) => u.copy(city = newCity), _.city)
val streetLens = addrStreetLens compose addressLens
val streetLensAlias = addrStreetLens <=< addressLens
val streetLensAndThen = addressLens andThen addrStreetLens
val streetLensAndThenAlias = addressLens >=> addrStreetLens
val cityLens = addressLens >=> addrCityLens
val postcodeLens = addressLens >=> addrPostcodeLens
// Starting value
val person = Person("Joe Grey", 37, Address("Southover Street", "Brighton", "BN2 9UA"))
// Read a field
val age1 = ageLens get person // Type inferred is Int
age1 == 37
// Update a field
val person2 = ageLens.set(person, 38)
person2.age == 38
// Transform a field
val person3 = ageLens.mod(_ + 1, person2)
person3.age == 39
val person3s = Seq(
(ageLens map (_ + 1)) run person2,
(ageLens %= (_ + 1)) run person2,
(ageLens >- (_ + 1)) run person2).unzip._1
person3s.forall(_.age == 39)
val nameState =
for {
x <- nameLens
_ <- nameLens := x + " Eh" }
yield x
val (person4, _) = nameState run person
person4.name == "Joe Grey Eh"
// Read a nested field
val street_ = streetLens get person3
street_ == "Southover Street"
// Update a nested field
val person5 = streetLens.set(person3, "Montpelier Road")
person5.address.street == "Montpelier Road"
// Cumulative result of above updates
person5 == Person("Joe Grey", 39, Address("Montpelier Road", "Brighton", "BN2 9UA"))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment