Skip to content

Instantly share code, notes, and snippets.

@seanparsons
Created September 21, 2012 14:23
Show Gist options
  • Save seanparsons/3761731 to your computer and use it in GitHub Desktop.
Save seanparsons/3761731 to your computer and use it in GitHub Desktop.
Playing with lenses.
// Note this requires scalaz-core 7.0 added to the classpath.
import scalaz._
import Scalaz._
import Lens._
case class Address(street: String, country: String)
case class User(name: String, address: Address)
val address = Address("Monkey Street", "England")
val user = User("Sean", address)
// This is painful:
println(user.copy(address = user.address.copy(street = "Test Street")))
// This is really painful just to add "10 " to the front of the address:
println(user.copy(address = user.address.copy(street = "10 " + address.street)))
// This bit is the only important bit --------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Lenses are a view to and from a field.
val addressStreetLens = lensu[Address, String]((address, newStreet) => address.copy(street = newStreet), address => address.street)
// Get and "set" the value:
println(addressStreetLens.get(address))
println(addressStreetLens.set(address, "Test Street"))
// Modify a value seemingly in place.
println(addressStreetLens.mod(street => "12 " + street, address))
// Also lenses compose and since you only ever need to create one instance of a lens (as they're pure) they can be re-used over and over.
val userAddressLens = lensu[User, Address]((user, newAddress) => user.copy(address = newAddress), user => user.address)
val userStreetLens = userAddressLens >=> addressStreetLens
// Drill down into the value we're interested in:
println(userStreetLens.get(user))
// Modify the value a couple of layers down:
println(userStreetLens.mod(street => "12 " + street, user))
// The full wonder of lenses is held within this URL: https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/Lens.scala
// Also partial lenses are here: https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/PLens.scala
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment