CompileOps

final
class CompileOps[F[_], G[_], O]

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

class Object
trait Matchable
class Any

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.

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.

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.

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.

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.

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

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

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

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
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.

Example
scala> import cats.effect.SyncIO
scala> Stream.range(0,100).take(5).covary[SyncIO].compile.last.unsafeRunSync()
res0: Option[Int] = Some(4)
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.

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)
def resource(implicit compiler: Compiler[F, [_] =>> Resource[G, _$191]]): CompileOps[F, [_] =>> Resource[G, _$192], 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.

def string(implicit ev: O <:< String): G[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.

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.

Example
scala> Stream("Hello ", "world!").compile.string
res0: String = Hello world!
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.

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)
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. Equivalent to to[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.

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)
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. Equivalent to to[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.

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)