Suma
Suma

Reputation: 34393

Map and fold a collection in Scala

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

Answers (1)

Mateusz Kubuszok
Mateusz Kubuszok

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

Related Questions