cats icon indicating copy to clipboard operation
cats copied to clipboard

Add TraverseFilter.mapAccumulateFilter

Open Masynchin opened this issue 1 year ago • 8 comments

If Traverse has mapAccumulate, why don't TraverseFilter has mapAccumulateFilter?

Now it has. I implement method itself (almost fully copied from mapAccumulate, changing traverse to traverseFilter), syntax ops, and tests (almost fully copied from mapAccumulate, adjusting fn signature)

Masynchin avatar Feb 19 '24 16:02 Masynchin

There is no override of mapAccumulate for Seq, so should it be added with mapAccumulateFilter through StaticMethods.mapAccumulateFilterFromStrictFunctorFilter?

Masynchin avatar Feb 19 '24 19:02 Masynchin

There is no override of mapAccumulate for Seq, so should it be added with mapAccumulateFilter through StaticMethods.mapAccumulateFilterFromStrictFunctorFilter?

Same for LazyList and Stream

Masynchin avatar Feb 19 '24 19:02 Masynchin

Bikeshed question: why mapAccumulateFilter vs mapFilterAccumulate?

I just added "Filter"-suffix after original method name from Traverse, same as in traversetraverseFilter and sequencesequenceFilter

I have no opinion here, I don't mind both

Masynchin avatar Mar 02 '24 13:03 Masynchin

There is no override of mapAccumulate for Seq, so should it be added with mapAccumulateFilter through StaticMethods.mapAccumulateFilterFromStrictFunctorFilter?

I think it can be addressed in a separate follow-up PR, just to avoid blowing up the scope of this one.

satorg avatar Apr 05 '24 07:04 satorg

  • Bikeshed question: why mapAccumulateFilter vs mapFilterAccumulate? I think I prefer the latter.
  • I just added "Filter"-suffix after original method name from Traverse, same as in traverse → traverseFilter and sequence → sequenceFilter

We just get to decide, whether the new method is likely mapFilter + Accumulate or mapAccumulate + Filter 😄

As a bit more crazy idea (maybe not that crazy though): we can add two functions instead:

def mapAccumulateFilter[S, A, B](init: S, fa: F[A])(f: (S, A) => (S, Option[B])): (S, F[B])
def mapFilterAccumulate[S, A, B](init: S, fa: F[A])(f: (S, A) => Option[(S, B)]): (S, F[B])

The former always does accumulate regardless of filter, hence the name. The latter always does filter first, then accumulate if not filtered out.

Of course, we can implement mapFilterAccumulate in terms of mapAccumulateFilter, e.g.:

def mapFilterAccumulate[S, A, B](init: S, fa: F[A])(f: (S, A) => Option[(S, B)]): (S, F[B]) =
  mapAccumulateFilter(init, fa) { (s1, a) =>
    f(s1, a) match {
      case (s2, Some(b)) => Some((s2, b))
      case (_, None) => None // drop `S` from this iteration
    }
  }

However both functions can come handy under certain circumstances. (sorry if my snippet is incorrect – it is beyond 1 am already and I am gravily sleepy)

Moreover, even more important – it could help up to avoid choosing between two really good names and just move on with this PR :)

satorg avatar Apr 05 '24 08:04 satorg

Of course, we can implement mapFilterAccumulate in terms of mapAccumulateFilter, e.g.:

def mapFilterAccumulate[S, A, B](init: S, fa: F[A])(f: (S, A) => Option[(S, B)]): (S, F[B]) =
  mapAccumulateFilter(init, fa) { (s1, a) =>
    f(s1, a) match {
      case (s2, Some(b)) => Some((s2, b))
      case (_, None) => None // drop `S` from this iteration
    }
  }

This is implementation of mapAccumulateFilter in terms of mapFilterAccumulate. f pattern matching should be changed inside out:

f(s1, a) match
  case Some((s2, b)) => (s2, Some(b))
  case None          => (s1, None)

Masynchin avatar Apr 05 '24 09:04 Masynchin

This is implementation of mapAccumulateFilter in terms of mapFilterAccumulate. f pattern matching should be changed inside out:

Yes, thank you 😊

Anyway, mapFilterAccumulate looks like a special case for mapAccumulateFilter, which is more general. But it can come more handy when accumulation is not needed on entries where the condition does not hold.

@armanbilge – wdyt?

satorg avatar Apr 05 '24 18:04 satorg

Hi there, just a check-up: where do we stand on this PR?

satorg avatar Dec 05 '24 04:12 satorg