Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/**
*
* LENS
*
*
*/
case class Street(name: String, number: Int)
case class Address(country: String, city: String, street: Street)
val bigStreet = Street("Unter den Linden", 3)
val address1 = Address("Germany", "Berlin", bigStreet)
case class User(id: Long, address: Address)
case class Account(id: Long, user: User, isActive: Boolean)
def changeStreetNumber(account: Account,
int: Int): Account =
account.copy(
user = account.user.copy(
address = account.user.address.copy(
street = account.user.address.street.copy(
number = int
)
)
)
)
val account = Account(1, User(2, address1), true)
case class Lens[A, B](
get: A => B,
set: (A, B) => A
)
val streetNumberLens = Lens[Street, Int](
get = _.number,
set = (a, b) => a.copy(number = b)
)
streetNumberLens.get(bigStreet)
streetNumberLens.set(bigStreet, 9)
//FROM THE BOOK: Functional And Reactive Domain Modeling
def compose[Outer, Inner, Value](
outer: Lens[Outer, Inner],
inner: Lens[Inner, Value]
) = Lens[Outer, Value](
get = outer.get andThen inner.get,
set = (obj, value) => outer.set(obj, inner.set(outer.get(obj), value))
)
val addressStreetLens = Lens[Address, Street](
get = _.street,
set = (a, b) => a.copy(street = b)
)
val addressStreetNumberLens: Lens[Address, Int] = compose(addressStreetLens, streetNumberLens)
/**
*
* PRISM
*
*/
sealed trait Pet
case class Dog(name: String) extends Pet
case class Cat(name: String) extends Pet
case object NoPetYet extends Pet
//this is a simplification of Prism
case class Prism[S, A](_getOption: S => Option[A])( _reverseGet: A => S ){
def getOption(s: S): Option[A] = _getOption(s)
def reverseGet(a: A): S = _reverseGet(a)
}
val petPrism: Prism[Pet, String] = Prism[Pet, String]{
case Dog(n) => Some(n)
case _ => None
}(name => Dog(name))
petPrism.getOption(Dog("Santa's Little Helper"))
petPrism.reverseGet("Santa's Little Helper")
/**
*
* OPTIONAL
*
*/
//this is a simplification of Optional
case class Optional[S, A](_getOption: S => Option[A])(_set: A => S => S){
def getOption(s: S): Option[A] = _getOption(s)
def set(a: A): S => S = _set(a)
}
sealed trait Box
case class Present(quantity: Int) extends Box
case object NoPresent extends Box
val maybePresents = Optional[Box, Int] {
case present: Present => Some(present.quantity)
case _ => None
}{ numberOfPresents => box => box match {
case present: Present => present.copy(quantity = numberOfPresents)
case _ => box
}
}
maybePresents.getOption(Present(3))
maybePresents.set(9)
/**
*
* LENS LAWS
*
*/
def getSet[S, A](lens: Lens[S, A], s: S): Boolean =
lens.set(s, lens.get(s)) == s
def setGet[S, A](lens: Lens[S, A], s: S, a: A): Boolean =
lens.get(lens.set(s, a)) == a
def putPut[S, A](lens: Lens[S, A], s: S, a: A, b: A): Boolean =
lens.get(lens.set(lens.set(s, a), b)) == b
val getSetLaw = getSet(streetNumberLens, Street("Pariser Str", 18))
val setGetLaw = setGet(streetNumberLens, Street("Pariser Str", 18), 5)
val putPutLaw = putPut(streetNumberLens, Street("Pariser Str", 18), 5, 3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.