Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying an attribute with Monocle Lenses using the value of another attribute

I have the following model

import monocle.macros.Lenses
import monocle.function.all._
import monocle.std.list._

@Lenses("_") case class Poll(pollChoices: List[PollChoice], totalVoteCount: Int)
@Lenses("_") case class PollChoice(id: Int, value: Int, percentage: Int)

What I'm trying to achieve is to update the pollChoices attribute of the Poll by updating all the percentage attributes of each element in the pollChoices List. My problem is that the new percentage values are based on the value attribute of the PollChoice and the totalValueCount of the Poll.

What I did so far is:

val poll = Poll(List(PollChoice(1,3,0), PollChoice(2,5,0)), 8)

(Poll._pollChoices composeTraversal each composeLens PollChoice._percentage)
  .modify(oldPercentage => oldPercentage + 1)(poll)

But this way i can only access the percentage attribute of the element I'm updating in the modify step, I also need the value.

I'm assuming I would need to use Traversable to do this kind of modification, but am not sure how. Thanks.

like image 389
Daniel B. Avatar asked Dec 13 '16 14:12

Daniel B.


1 Answers

I don't think that you can express this in a single lens, but a separate lens inside .modify works well:

Poll._pollChoices.composeTraversal(each).modify { choice =>
  PollChoice._percentage.set(choice.value / poll.totalVoteCount)(choice)
}(poll)
like image 171
lunaryorn Avatar answered Oct 09 '22 04:10

lunaryorn