New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Iterant.foldWhileLeftL and Iterant.foldWhileLeftEvalL #403

Merged
merged 2 commits into from Aug 7, 2017

Conversation

Projects
None yet
1 participant
@alexandru
Member

alexandru commented Aug 7, 2017

This adds 2 foldLeft-like operators to Iterant that are supposed to be a more efficient, but less powerful replacement for a foldRight.

The strict version:

def foldWhileLeftL[S](seed: => S)(op: (S, A) => Either[S, S])
  (implicit F: Sync[F]): F[S]

And the lazy version:

def foldWhileLeftEvalL[S](seed: F[S])(op: (S, A) => F[Either[S, S]])
  (implicit F: Sync[F]): F[S]

Note, these signatures are methods, this is implied to be Iterant[F, A].

What this adds over regular foldLeft:

  1. the ability to short-circuit processing, such that operators like exists and forall can be expressed with it
  2. the ability to describe side effects with lazy or asynchronous execution (second variant)

Examples given in the ScalaDoc:

// Sums first 10 items
Iterant[Task].range(0, 1000).foldWhileLeftL((0, 0)) {
  case ((sum, count), e) =>
    val next = (sum + e, count + 1)
    if (count + 1 < 10) Left(next) else Right(next)
}

// Implements exists(predicate)
Iterant[Task].of(1, 2, 3, 4, 5).foldWhileLeftL(false) {
  (default, e) =>
    if (e == 3) Right(true) else Left(default)
}

// Implements forall(predicate)
Iterant[Task].of(1, 2, 3, 4, 5).foldWhileLeftL(true) {
  (default, e) =>
    if (e != 3) Right(false) else Left(default)
}

And for the F[_] enabled version:

// Sums first 10 items
Iterant[IO].range(0, 1000).foldWhileLeftEvalL(IO((0, 0))) {
  case ((sum, count), e) =>
    IO {
      val next = (sum + e, count + 1)
      if (count + 1 < 10) Left(next) else Right(next)
    }
}

// Implements exists(predicate)
Iterant[IO].of(1, 2, 3, 4, 5).foldWhileLeftEvalL(IO(false)) {
  (default, e) =>
    IO { if (e == 3) Right(true) else Left(default) }
}

// Implements forall(predicate)
Iterant[IO].of(1, 2, 3, 4, 5).foldWhileLeftEvalL(IO(true)) {
  (default, e) =>
    IO { if (e != 3) Right(false) else Left(default) }
}
@codecov

This comment has been minimized.

codecov bot commented Aug 7, 2017

Codecov Report

Merging #403 into master will increase coverage by 0.17%.
The diff coverage is 95.55%.

@@            Coverage Diff             @@
##           master     #403      +/-   ##
==========================================
+ Coverage   88.19%   88.37%   +0.17%     
==========================================
  Files         338      340       +2     
  Lines        9042     9181     +139     
  Branches     1189     1198       +9     
==========================================
+ Hits         7975     8114     +139     
  Misses       1067     1067

@alexandru alexandru changed the title from Add Iterant.foldUntilRightL and Iterant.foldUntilRightEvalL to Add Iterant.foldWhileLeftL and Iterant.foldWhileLeftEvalL Aug 7, 2017

@alexandru alexandru merged commit cfb43ff into monix:master Aug 7, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

@alexandru alexandru added this to the 3.0.0 milestone Jan 21, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment