Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

add filter, deprecate unsafeSelect #988

Merged
merged 2 commits into from
Dec 11, 2020
Merged

add filter, deprecate unsafeSelect #988

merged 2 commits into from
Dec 11, 2020

Conversation

julien-truffaut
Copy link
Member

@julien-truffaut julien-truffaut commented Dec 10, 2020

This PR adds Optional.filter and filter method on all Optics and ApplyOptics.

filter allows to select the targets which satisfy a predicate, for example:

val positiveNumbers = Traversal.fromTraverse[List, Int].filter(_ > 0)
val list = List(1,2,-3,4,-5)

positiveNumbers.getAll(list) == List(1,2,4)
positiveNumbers.modify(_ * 10)(list) == List(10,20,-3,40,-5) // only the positive numbers are multiplied by 10

filter can break the fusion law that says that modify(f).modify(g) == modify(f andThen g), for example:

val list       = List(1, 5, -3)
val firstStep  = positiveNumbers.modify(_ - 3)(list)            // List(-2, 2, -3)
val secondStep = positiveNumbers.modify(_ * 2)(firstStep)       // List(-2, 4, -3)
val bothSteps  = positiveNumbers.modify(x => (x - 3) * 2)(list) // List(-4, 4, -3)

In bothSteps, the first value is -4 = (1 - 3) * 2 but in secondStep it is -2 = (1 - 3).
The second update _ * 2 wasn't applied because the target became negative after the first update _ - 3.

In other words, filter breaks the property if replace or modify invalidate the predicate.

A safe usage would be to filter on one field and update another one, for example:

case class User(name: String, coins: Int, address: Address)
case class Address(line1: String, country: String)

val users: Traversal[State, User] = ...
val coins: Lens[User, Int] = ...

users
  .filter(_.address.country == "UK")
  .andThen(coins)
  .modify(_ - 5) // remove 5 coins to all UK users

Copy link
Collaborator

@cquiroz cquiroz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, this will be useful

@jdegoes
Copy link
Contributor

jdegoes commented Dec 10, 2020

Yes, please!

@julien-truffaut julien-truffaut merged commit ec4d877 into master Dec 11, 2020
@julien-truffaut julien-truffaut deleted the filter-select branch December 11, 2020 08:51
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants