CompileOps

fs2.Stream.CompileOps
final class CompileOps[F[_], G[_], O]

Projection of a Stream providing various ways to compile a Stream[F,O] to a G[...].

Attributes

Source
Stream.scala
Graph
Supertypes
class Object
trait Matchable
class Any

Members list

Value members

Concrete methods

def count: G[Long]

Compiles this stream to a count of the elements in the target effect type G.

Compiles this stream to a count of the elements in the target effect type G.

Attributes

Source
Stream.scala
def drain: G[Unit]

Compiles this stream in to a value of the target effect type G and discards any output values of the stream.

Compiles this stream in to a value of the target effect type G and discards any output values of the stream.

To access the output values of the stream, use one of the other compilation methods -- e.g., fold, toVector, etc.

Attributes

Source
Stream.scala
def fold[B](init: B)(f: (B, O) => B): G[B]

Compiles this stream in to a value of the target effect type G by folding the output values together, starting with the provided init and combining the current value with each output value.

Compiles this stream in to a value of the target effect type G by folding the output values together, starting with the provided init and combining the current value with each output value.

Attributes

Source
Stream.scala
def foldChunks[B](init: B)(f: (B, Chunk[O]) => B): G[B]

Compiles this stream in to a value of the target effect type G by folding the output chunks together, starting with the provided init and combining the current value with each output chunk.

Compiles this stream in to a value of the target effect type G by folding the output chunks together, starting with the provided init and combining the current value with each output chunk.

When this method has returned, the stream has not begun execution -- this method simply compiles the stream down to the target effect type.

Attributes

Source
Stream.scala
def foldMonoid(implicit O: Monoid[O]): G[O]

Like fold but uses the implicitly available Monoid[O] to combine elements.

Like fold but uses the implicitly available Monoid[O] to combine elements.

Attributes

Example

scala> import cats.effect.SyncIO
scala> Stream(1, 2, 3, 4, 5).covary[SyncIO].compile.foldMonoid.unsafeRunSync()
res0: Int = 15
Source
Stream.scala
def foldSemigroup(implicit O: Semigroup[O]): G[Option[O]]

Like fold but uses the implicitly available Semigroup[O] to combine elements.

Like fold but uses the implicitly available Semigroup[O] to combine elements. If the stream emits no elements, None is returned.

Attributes

Example

scala> import cats.effect.SyncIO
scala> Stream(1, 2, 3, 4, 5).covary[SyncIO].compile.foldSemigroup.unsafeRunSync()
res0: Option[Int] = Some(15)
scala> Stream.empty.covaryAll[SyncIO, Int].compile.foldSemigroup.unsafeRunSync()
res1: Option[Int] = None
Source
Stream.scala
def last: G[Option[O]]

Compiles this stream in to a value of the target effect type G, returning None if the stream emitted no values and returning the last value emitted wrapped in Some if values were emitted.

Compiles this stream in to a value of the target effect type G, returning None if the stream emitted no values and returning the last value emitted wrapped in Some if values were emitted.

When this method has returned, the stream has not begun execution -- this method simply compiles the stream down to the target effect type.

Attributes

Example

scala> import cats.effect.SyncIO
scala> Stream.range(0,100).take(5).covary[SyncIO].compile.last.unsafeRunSync()
res0: Option[Int] = Some(4)
Source
Stream.scala
def lastOrError(implicit G: MonadError[G, Throwable]): G[O]

Compiles this stream in to a value of the target effect type G, raising a NoSuchElementException if the stream emitted no values and returning the last value emitted otherwise.

Compiles this stream in to a value of the target effect type G, raising a NoSuchElementException if the stream emitted no values and returning the last value emitted otherwise.

When this method has returned, the stream has not begun execution -- this method simply compiles the stream down to the target effect type.

Attributes

Example

scala> import cats.effect.SyncIO
scala> Stream.range(0,100).take(5).covary[SyncIO].compile.lastOrError.unsafeRunSync()
res0: Int = 4
scala> Stream.empty.covaryAll[SyncIO, Int].compile.lastOrError.attempt.unsafeRunSync()
res1: Either[Throwable, Int] = Left(java.util.NoSuchElementException)
Source
Stream.scala
def onlyOrError(implicit G: MonadError[G, Throwable]): G[O]

Compiles this stream in to a value of the target effect type G, raising a NoSuchElementException if the stream emitted no values, IllegalStateException if the stream emits more than one value and returning the only value emitted otherwise.

Compiles this stream in to a value of the target effect type G, raising a NoSuchElementException if the stream emitted no values, IllegalStateException if the stream emits more than one value and returning the only value emitted otherwise. Note that the stream execution will not short-circuit once it emits more than one element, it will still be evaluated to its end before raising the exception.

When this method has returned, the stream has not begun execution -- this method simply compiles the stream down to the target effect type.

Attributes

Example

scala> import cats.effect.SyncIO
scala> Stream(1).covary[SyncIO].compile.onlyOrError.unsafeRunSync()
res0: Int = 1
scala> Stream.empty.covaryAll[SyncIO, Int].compile.onlyOrError.attempt.unsafeRunSync()
res1: Either[Throwable, Int] = Left(java.util.NoSuchElementException)
scala> Stream.range(0,10).covary[SyncIO].compile.onlyOrError.attempt.unsafeRunSync()
res2: Either[Throwable, Int] = Left(java.lang.IllegalStateException: Expected singleton stream)
Source
Stream.scala
def resource(implicit compiler: Compiler[F, [_] =>> Resource[G, _$210]]): CompileOps[F, [_] =>> Resource[G, _$211], O]

Gives access to the whole compilation api, where the result is expressed as a cats.effect.Resource, instead of bare G.

Gives access to the whole compilation api, where the result is expressed as a cats.effect.Resource, instead of bare G.

import fs2._
import cats.effect._

val stream = Stream.iterate(0)(_ + 1).take(5).covary[IO]

val s1: Resource[IO, List[Int]] = stream.compile.resource.toList
val s2: Resource[IO, Int] = stream.compile.resource.foldMonoid
val s3: Resource[IO, Option[Int]] = stream.compile.resource.last

And so on for every other method in compile.

The main use case is interacting with Stream methods whose behaviour depends on the Stream lifetime, in cases where you only want to ultimately return a single element.

A typical example of this is concurrent combinators, here is an example with concurrently:

import fs2._
import cats.effect._
import cats.effect.kernel.Ref
import scala.concurrent.duration._

trait StopWatch[F[_]] {
 def elapsedSeconds: F[Int]
}
object StopWatch {
 def create[F[_]](implicit F: Temporal[F]): Stream[F, StopWatch[F]] =
   Stream.eval(F.ref(0)).flatMap { c =>
     val api = new StopWatch[F] {
       def elapsedSeconds: F[Int] = c.get
     }

     val process = Stream.fixedRate(1.second).evalMap(_ => c.update(_ + 1))

     Stream.emit(api).concurrently(process)
 }
}

This creates a simple abstraction that can be queried by multiple consumers to find out how much time has passed, with a concurrent stream to update it every second.

Note that create returns a Stream[F, StopWatch[F]], even though there is only one instance being emitted: this is less than ideal, so we might think about returning an F[StopWatch[F]] with the following code

StopWatch.create[F].compile.lastOrError

but it does not work: the returned F terminates the lifetime of the stream, which causes concurrently to stop the process stream. As a result, elapsedSeconds never gets updated.

Alternatively, we could implement StopWatch in F only using Fiber.start, but this is not ideal either: concurrently already handles errors, interruption and stopping the producer stream once the consumer lifetime is over, and we don't want to reimplement the machinery for that.

So basically what we need is a type that expresses the concept of lifetime, while only ever emitting a single element, which is exactly what cats.effect.Resource does.

What compile.resource provides is the ability to do this:

object StopWatch {
 // ... def create as before ...

 def betterCreate[F[_]: Temporal]: Resource[F, StopWatch[F]] =
   create.compile.resource.lastOrError
}

This works for every other compile. method, although it's a very natural fit with lastOrError.

Attributes

Source
Stream.scala
def string(implicit ev: O <:< String): G[String]

Compiles this stream of strings in to a single string.

Compiles this stream of strings in to a single string. This is more efficient than foldMonoid because it uses a StringBuilder internally, avoiding intermediate string creation.

Attributes

Example

scala> Stream("Hello ", "world!").compile.string
res0: String = Hello world!
Source
Stream.scala
def to(collector: Collector[O]): G[Out]

Compiles this stream into a value of the target effect type G by collecting all of the output values in a collection.

Compiles this stream into a value of the target effect type G by collecting all of the output values in a collection.

Collection building is done via an explicitly passed Collector. Standard library collections have collector instances, allowing syntax like: s.compile.to(List) or s.compile.to(Array) or s.compile.to(Map).

A collector is provided for scodec.bits.ByteVector, providing efficient byte vector construction from a stream of bytes: s.compile.to(ByteVector).

When this method has returned, the stream has not begun execution -- this method simply compiles the stream down to the target effect type.

Attributes

Example

scala> import cats.effect.SyncIO
scala> val s = Stream.range(0,100).take(5).covary[SyncIO]
scala> s.compile.to(List).unsafeRunSync()
res0: List[Int] = List(0, 1, 2, 3, 4)
scala> s.compile.to(Chunk).unsafeRunSync()
res1: Chunk[Int] = Chunk(0, 1, 2, 3, 4)
scala> s.map(i => (i % 2, i)).compile.to(Map).unsafeRunSync()
res2: Map[Int, Int] = Map(0 -> 4, 1 -> 3)
scala> s.map(_.toByte).compile.to(scodec.bits.ByteVector).unsafeRunSync()
res3: scodec.bits.ByteVector = ByteVector(5 bytes, 0x0001020304)
Source
Stream.scala
def toList: G[List[O]]

Compiles this stream in to a value of the target effect type G by logging the output values to a List.

Compiles this stream in to a value of the target effect type G by logging the output values to a List. Equivalent to to[List].

When this method has returned, the stream has not begun execution -- this method simply compiles the stream down to the target effect type.

Attributes

Example

scala> import cats.effect.SyncIO
scala> Stream.range(0,100).take(5).covary[SyncIO].compile.toList.unsafeRunSync()
res0: List[Int] = List(0, 1, 2, 3, 4)
Source
Stream.scala
def toVector: G[Vector[O]]

Compiles this stream in to a value of the target effect type G by logging the output values to a Vector.

Compiles this stream in to a value of the target effect type G by logging the output values to a Vector. Equivalent to to[Vector].

When this method has returned, the stream has not begun execution -- this method simply compiles the stream down to the target effect type.

Attributes

Example

scala> import cats.effect.SyncIO
scala> Stream.range(0,100).take(5).covary[SyncIO].compile.toVector.unsafeRunSync()
res0: Vector[Int] = Vector(0, 1, 2, 3, 4)
Source
Stream.scala