Skip to content

Commit

Permalink
Merge pull request #1594 from ChristopherDavenport/streamLoop
Browse files Browse the repository at this point in the history
Add combinator unfoldLoopEval
  • Loading branch information
mpilquist authored Sep 9, 2019
2 parents 0d382ba + 58ff8bf commit f18b674
Showing 1 changed file with 31 additions and 0 deletions.
31 changes: 31 additions & 0 deletions core/shared/src/main/scala/fs2/Stream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3576,6 +3576,37 @@ object Stream extends StreamLowPriority {
suspend(go(s))
}

/**
* Creates a stream by successively applying `f` to a `S`, emitting
* each output `O` and using each output `S` as input to the next invocation of `f`
* if it is Some, or terminating on None
*
* @example {{{
* scala> Stream.unfoldLoop(0)(i => (i, if (i < 5) Some(i+1) else None)).toList
* res0: List[Int] = List(0, 1, 2, 3, 4, 5)
* }}}
*/
def unfoldLoop[F[x] <: Pure[x], S, O](s: S)(f: S => (O, Option[S])): Stream[F, O] =
Pull.loop[F, O, S]{
s =>
val (o, sOpt) = f(s)
Pull.output1(o) >> Pull.pure(sOpt)
}(s)
.void
.stream

/** Like [[unfoldLoop]], but takes an effectful function. */
def unfoldLoopEval[F[_], S, O](s: S)(f: S => F[(O, Option[S])]): Stream[F, O] =
Pull
.loop[F, O, S](
s =>
Pull.eval(f(s)).flatMap {
case (o, sOpt) => Pull.output1(o) >> Pull.pure(sOpt)
}
)(s)
.void
.stream

/** Provides syntax for streams that are invariant in `F` and `O`. */
implicit def InvariantOps[F[_], O](s: Stream[F, O]): InvariantOps[F, O] =
new InvariantOps(s.get)
Expand Down

0 comments on commit f18b674

Please sign in to comment.