CompileOps
Projection of a
Stream
providing various ways to compile a Stream[F,O]
to a G[...]
.class Object
trait Matchable
class Any
Value members
Methods
Compiles this stream in to a value of the target effect type
the output values together, starting with the provided
current value with each output value.
F
by foldingthe output values together, starting with the provided
init
and combining thecurrent value with each output value.
Compiles this stream in to a value of the target effect type
the output chunks together, starting with the provided
current value with each output chunk.
F
by foldingthe output chunks together, starting with the provided
init
and combining thecurrent 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.
compiles the stream down to the target effect type.
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
}}}
Like fold but uses the implicitly available
If the stream emits no elements,
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
}}}
Compiles this stream in to a value of the target effect type
returning
last value emitted wrapped in
F
,returning
None
if the stream emitted no values and returning thelast 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.
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)
}}}
Compiles this stream in to a value of the target effect type
raising a
and returning the last value emitted otherwise.
F
,raising a
NoSuchElementException
if the stream emitted no valuesand 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.
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(compiler: Compiler[F, [_$173] =>> Resource[G, _$173]]): CompileOps[F, [_$174] =>> Resource[G, _$174], O]
Gives access to the whole compilation api, where the result is
expressed as a
expressed as a
cats.effect.Resource
, instead of bare F
.{{{
import fs2._
import cats.effect._
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
}}}
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.
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
an example with
concurrently
:{{{
import fs2._
import cats.effect._
import cats.effect.kernel.Ref
import scala.concurrent.duration._
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
}
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.
multiple consumers to find out how much time has passed, with
a concurrent stream to update it every second.
Note that
though there is only one instance being emitted: this is less than ideal,
so we might think about returning an
create
returns a Stream[F, StopWatch[F]]
, eventhough 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
}}}
StopWatch.create[F] .compile.lastOrError
}}}
but it does not work: the returned
which causes
never gets updated.
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
using
stopping the producer stream once the consumer lifetime is
over, and we don't want to reimplement the machinery for that.
StopWatch
in F
onlyusing
Fiber.start
, but this is not ideal either:concurrently
already handles errors, interruption andstopping 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
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 ...
object StopWatch {
// ... def create as before ...
def betterCreate[F[_]
: Temporal]: Resource[F, StopWatch[F]
] =
create.compile.resource.lastOrError
}
}}}
create.compile.resource.lastOrError
}
}}}
This works for every other
very natural fit with
compile.
method, although it's avery natural fit with
lastOrError
.Compiles this stream of strings in to a single string.
This is more efficient than
internally, avoiding intermediate string creation.
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!
}}}
Compiles this stream into a value of the target effect type
all of the output values in a collection.
F
by collectingall of the output values in a collection.
Collection building is done via an explicitly passed
Standard library collections have collector instances, allowing syntax like:
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
vector construction from a stream of bytes:
scodec.bits.ByteVector
, providing efficient bytevector 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.
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)
}}}
Compiles this stream in to a value of the target effect type
the output values to a
F
by loggingthe 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.
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)
}}}
Compiles this stream in to a value of the target effect type
the output values to a
F
by loggingthe 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.
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)
}}}