Reputation: 34393
I have a fold
which iterates through elements, dependently modifies them one by one and at the same time modifies their parent.
Currently I replace the elements in their parent one by one in the fold
, they are just few and it is not a real performance issue, but I wonder if there is perhaps a nicer way to express this.
case class Behavior(x: Int) {
def simulate(s: Entity): Behavior = copy(x = x + (if (s.alternate) 2 else 1))
}
case class Entity(alternate: Boolean, behaviors: List[Behavior]) {
def replaceBehavior(o: Behavior, n: Behavior): Entity = {
copy(behaviors = behaviors.patch(behaviors.indexOf(o), Seq(n), 1))
}
def toggleAlternate: Entity = copy(alternate = !alternate)
def simulate: Entity = {
behaviors.foldLeft(this) { (e, b) =>
e.replaceBehavior(b, b.simulate(e)).toggleAlternate
}
}
}
val entity = Entity(false, List(Behavior(10), Behavior(20), Behavior(30)))
entity.simulate
Is there some operation or perhaps some clever use of scan
or something like that which would allow me to perform foldLeft
and map
dependent of the foldLeft
result in one step? (I would prefer vanilla standard Scala library, but using functional frameworks is possible too).
Upvotes: 0
Views: 244
Reputation: 27535
Folds (fold
, foldLeft
, foldRight
, ...) usually turn some Collection[A]
into B
.
You could map over A
before folding result to B
- foldMap
maps A => B
and assumed existence of Monoid[B]
(this is available in Cats in Foldable
typeclass), so you would perform transformation Collection[A] --using f--> Collection[B] --using Monoid[B]--> B
(code can optimize it to perform things in one step using e.g. foldLeft
internally).
Reversing the order of operations - we fold
and then we map
- is in general impossible because there is nothing that can let us assume that after fold
step we will end up with something that is a Functor
.
Depending on your specific use case we might try using foldMap
to achieve your goal.
Upvotes: 2