Skip to content

Commit

Permalink
Add Iterant.scanMap (#523)
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasil authored and alexandru committed Jan 15, 2018
1 parent 7ca7c0d commit 6760150
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
29 changes: 29 additions & 0 deletions monix-tail/shared/src/main/scala/monix/tail/Iterant.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,35 @@ sealed abstract class Iterant[F[_], A] extends Product with Serializable {
final def scanEval[S](seed: F[S])(op: (S, A) => F[S])(implicit F: Sync[F]): Iterant[F, S] =
IterantScanEval(self, seed, op)

/** Given a mapping function that returns a `B` type for which we have
* a [[cats.Monoid]] instance, returns a new stream that folds the incoming
* elements of the sources using the provided `Monoid[B].combine`, with the
* initial seed being the `Monoid[B].empty` value, emitting the generated values
* at each step.
*
* Equivalent with [[scan]] applied with the given [[cats.Monoid]], so given
* our `f` mapping function returns a `B`, this law holds:
* {{{
* val B = implicitly[Monoid[B]]
*
* stream.scanMap(f) <-> stream.scan(B.empty)(B.combine)
* }}}
*
* Example:
* {{{
* // Yields 2, 6, 12, 20, 30, 42
* Iterant[Task].of(1, 2, 3, 4, 5, 6).scanMap(x => x * 2)
* }}}
*
* @param f is the mapping function applied to every incoming element of this `Iterant`
* before folding using `Monoid[B].combine`
*
* @return a new `Iterant` that emits all intermediate states being
* resulted from applying `Monoid[B].combine` function
*/
final def scanMap[B](f: A => B)(implicit F: Sync[F], B: Monoid[B]): Iterant[F, B] =
self.scan(B.empty)((acc, a) => B.combine(acc, f(a)))

/** Skips over [[Iterant.Suspend]] states, along with
* [[Iterant.NextCursor]] and [[Iterant.NextBatch]] states that
* signal empty collections.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2014-2018 by The Monix Project Developers.
* See the project homepage at: https://monix.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package monix.tail

import cats.laws._
import cats.laws.discipline._
import monix.eval.Coeval

object IterantScanMapSuite extends BaseTestSuite {

test("Iterant.scanMap equivalence to Iterant.scan") { implicit s =>
check1 { (source: Iterant[Coeval, Int]) =>
val scanned1 = source.scanMap(x => x)
val scanned2 = source.scan(0)(_ + _)

val fa1 = scanned1
.takeWhile(_ < 10)

val fa2 = scanned2
.takeWhile(_ < 10)

fa1.toListL <-> fa2.toListL
}
}
}

0 comments on commit 6760150

Please sign in to comment.