Created
April 28, 2020 14:29
-
-
Save fancellu/a5288e1967809f67e051a5ded21575f8 to your computer and use it in GitHub Desktop.
Example usage of the Monocle Optics library showing manipulation of deeply nested immutable objects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import monocle.{Iso, Prism} | |
import monocle.macros.syntax.lens._ | |
import monocle.macros.GenIso | |
object LensApp extends App{ | |
case class Street(number: Int, name: String) | |
case class Address(city: String, street: Street, postcode: Option[String]=None) | |
case class Company(name: String, address: Address) | |
sealed trait Gender | |
case object Male extends Gender | |
case object Female extends Gender | |
case class Other(v: String) extends Gender | |
case class Employee(name: String, gender: Gender, company: Company) | |
val genderString = Prism.partial[Gender, String]{ | |
case Other(v) => s"gender: $v" | |
case Male=> "man" | |
case Female=> "woman" | |
}(Other) | |
val employee = Employee("Alan", Other("Apache Attack Helicopter"), Company("Twitter", Address("London", Street(12, "high street")))) | |
println(employee) | |
val genderOption=employee.lens(_.gender).composePrism(genderString).getOption | |
println(genderOption) | |
val employeePostcode: Option[String] =employee.lens(_.company.address.postcode).get | |
println(s"employeePostcode=$employeePostcode") | |
println("We update employee") | |
val updatedemployee: Employee =employee.lens(_.company.address.street.name).modify(_.toUpperCase) | |
.lens(_.company.address.postcode).set(Some("KT18 4AL")) | |
.lens(_.name).set("james") | |
.lens(_.gender).set(Male) | |
println(updatedemployee) | |
val genderOption2=updatedemployee.lens(_.gender).composePrism(genderString).getOption | |
println(genderOption2) | |
val updatedemployeeAddress: Address =updatedemployee.lens(_.company.address).get | |
println(updatedemployeeAddress) | |
// define isomorphic mapping from tuple to case class, and case class to tuple | |
val streetToTuple = Iso[Street, (Int, String)](st => (st.number, st.name)){case (number, name) => Street(number, name)} | |
val streetToTupleCase = Iso[Street, (Int, String)](Street.unapply(_).get)(Street.tupled) | |
val streetToTupleGen = GenIso.fields[Street] | |
println(streetToTuple(23,"ISO Lane")) | |
println(streetToTupleCase(24,"ISO Lane")) | |
println(streetToTupleGen(25,"ISO Lane")) | |
val updatedemployeePostcode: Option[String] =updatedemployee.lens(_.company.address.postcode).get | |
println(s"updatedemployeePostcode=$updatedemployeePostcode") | |
val street: Street =updatedemployee.lens(_.company.address.street).get | |
println(street) | |
println(streetToTupleCase.get(street)) | |
val streetTuple: (Int, String) =updatedemployee.lens(_.company.address.street).composeIso(streetToTupleCase).get | |
println(streetTuple) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Employee(Alan,Other(Apache Attack Helicopter),Company(Twitter,Address(London,Street(12,high street),None))) | |
Some(gender: Apache Attack Helicopter) | |
employeePostcode=None | |
We update employee | |
Employee(james,Male,Company(Twitter,Address(London,Street(12,HIGH STREET),Some(KT18 4AL)))) | |
Some(man) | |
Address(London,Street(12,HIGH STREET),Some(KT18 4AL)) | |
Street(23,ISO Lane) | |
Street(24,ISO Lane) | |
Street(25,ISO Lane) | |
updatedemployeePostcode=Some(KT18 4AL) | |
Street(12,HIGH STREET) | |
(12,HIGH STREET) | |
(12,HIGH STREET) | |
Process finished with exit code 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment