Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ### FoldLeftSC
- > A `Foldable.foldLeft`implementation that short-circuits on a given predicate
- ---
- The first attempt was a failure. Using `foldM` and `Option`.
- ```scala
- def foldLeft[F[_]: Foldable, A, B](fa: F[A])(b: B)(f: (B, A) => B)(p: B => Boolean): B =
- Foldable[F].foldM[Option,A,B](fa, b) {
- case (b, a) if !p(b) => none or b.some
- case (b, a) => f(b,a).some
- }.getOrElse(b)
- ```
- Both implementation did actually not do what we want:
- - The first one, using none, will short-circuit as expected but will always return none.
- - The second one, using some, will accumulate while skipping the elements that do not fulfill the predicate.
- The solution is use `foldM` but `Either[B,B]` instead of `Option`:
- ```scala
- def foldLeft[F[_]: Foldable, A, B](fa: F[A])(b: B)(f: (B, A) => B)(p: B => Boolean): B =
- Foldable[F].foldM[Either[B, ?],A,B](fa, b) {
- case (b, a) if !p(b) => b.asLeft
- case (b, a) => f(b,a).asRight
- } match {
- case Left(b) => b
- case Righ(b) => b
- }
- // Should return 3
- foldLeft(List(1,2,3,4,5))(0)(_ + _)(_ < 3)
- // res0: 3
- ```
- Which is actually the same as `traverse` :-)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement