sealed abstract class Pull[+F[_], +O, +R] extends AnyRef
A purely functional data structure that describes a process. This process
may evaluate actions in an effect type F, emit any number of output values
of type O (or None), and may a) terminate with a single result of type R;
or b) terminate abnormally by raising (inside the effect F) an exception,
or c) terminate because it was cancelled by another process,
or d) not terminate.
Like types from other effect libraries, pulls are pure and immutable values. They preserve referential transparency.
Chunking
The output values of a pull are emitted not one by one, but in chunks.
A Chunk is an immutable sequence with constant-time indexed lookup. For example,
a pull p: Pull[F, Byte, R] internally operates and emits Chunk[Byte]
values, which can wrap unboxed byte arrays -- avoiding boxing/unboxing costs.
The Pull API provides mechanisms for working at both the chunk level and
the individual element level. Generally, working at the chunk level will
result in better performance but at the cost of more complex implementations
A pull only emits non-empty chunks.
However, chunks are not merely an operational matter of efficiency. Each pull is emitted from a chunk atomically, which is to say, any errors or interruptions in a pull can only happen between chunks, not within a chunk. For instance, if creating a new chunk of values fails (raises an uncaught exception) while creating an intermediate value, then it fails to create the entire chunk and previous values are discarded.
Evaluation
Like other functional effect types (e.g. cats.effect.IO), a pull
describes a _process_ or _computation_. It is not a running process nor a
handle for the result of a spawned, running process, like scala.concurrent.Future.
A pull can be converted to a stream and then compiled to an effectful value.
For a Pull[F, O, Unit], the result of compilation is a combination, via the
monad instance of F, of all the actions in the effect F present in the pull.
The result of that F action is the result of combining the outputs emitted by
the pull, in the order it emits them, using a _fold_ function. Depending on that
function, outputs may be collected into a list (or vector or array or ...),
combined together into a single value, or just discarded altogether (by _draining_
the pull).
Compilation is pull-based, rather than push-based (hence the name of the datatype). It is the compilation process itself, that determines when the evaluation of each single effect can proceed or is held back. Effects and outputs later in the pull are not performed or emitted, _unless and until_ the compilation calls for them.
Resource scoping
The effects in a Pull may operate on resources, which must be retained during
the execution of the pull, may be shared by several pulls, and must be
properly finalised when no longer needed, regardless of whether the pull completed
successfully or not. A pull tracks its resources using scopes, which register
how many pulls are actively using each resource, and finalises resources when no
longer used.
Some operations of the Pull API can be used to introduce new resource scopes,
or resource boundaries.
Functional typeclasses
The Pull data structure is a "free" implementation of Monad and has an instance
for cats.effect.kernel.Sync.
For any types F[_] and O, a Pull[F, O, *] holds the following laws:
pure >=> f == ff >=> pure == f(f >=> g) >=> h == f >=> (g >=> h)wheref >=> gis defined asa => a flatMap f flatMap ghandleErrorWith(raiseError(e))(f) == f(e)
- O
The outputs emitted by this Pull. An output type of
Nothingmeans that this pull does not emit any outputs.- R
The type of result returned by this Pull upon successful termination. An output type of
Nothingindicates that this pull cannot terminate successfully: it may fail, be cancelled, or never terminate.
- Source
- Pull.scala
- Alphabetic
- By Inheritance
- Pull
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Value Members
-
final
def
!=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
##(): Int
- Definition Classes
- AnyRef → Any
-
final
def
==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
>>[F2[x] >: F[x], O2 >: O, S](post: ⇒ Pull[F2, O2, S]): Pull[F2, O2, S]
Lazily appends the given
postpull, to be run afterthispull.Lazily appends the given
postpull, to be run afterthispull.- If
thispull succeeds, then its result is discarded, thepostpull is built, and starts running. The result ofpostis the result of the composed pull.- If
thispull raises an error or is interrupted, thepostargument is not evaluated and the composed pull ends just asthispull did.In both cases, the effectful actions and outputs of the appended pull consists of those outputs and actions from the first pull, followed by those from the
postpull, in the same order as they would come out of each pull.Since the
postargument is lazy, this method can be used to build lazy pulls, which are not built in memory until after the prefix has run. This allows defining pulls recursively.This operation does not add or remove any resource scope boundaries. The
postpull runs on the same scope in whichthispull ended. The composed pull ends on whatever scope thepostpull does.This is equivalent to
.flatMap(_ => post) -
def
as[S](s: S): Pull[F, O, S]
Replaces the result of this pull with the given constant value.
Replaces the result of this pull with the given constant value. If
thispull succeeds, then its result is discarded and the resulting pull succeeds with thesvalue as its result. Otherwise, ifthispull fails or is interrupted, then the result pull ends the same way.Alias for
_.map(_ => o2).- S
The type of the constant,
- s
The new result value of the pull
-
final
def
asInstanceOf[T0]: T0
- Definition Classes
- Any
-
def
attempt: Pull[F, O, Either[Throwable, R]]
Returns a pull with the result wrapped in
Right, or an error wrapped inLeftif the pull has raised an error.Returns a pull with the result wrapped in
Right, or an error wrapped inLeftif the pull has raised an error. Ifthispull is interrupted, the attempted pull ends the same way. -
def
clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( ... ) @native()
-
def
covary[F2[x] >: F[x]]: Pull[F2, O, R]
Short-hand for
(this: Pull[F2, O, R]).Short-hand for
(this: Pull[F2, O, R]). Used to assist with type inference. -
def
covaryAll[F2[x] >: F[x], O2 >: O, R2 >: R]: Pull[F2, O2, R2]
Short-hand for
(this: Pull[F2, P, S]).Short-hand for
(this: Pull[F2, P, S]). Used to assist with type inference. -
def
covaryOutput[O2 >: O]: Pull[F, O2, R]
Short-hand for
(this: Pull[F, O2, R]).Short-hand for
(this: Pull[F, O2, R]). Used to assist with type inference. -
def
covaryResult[R2 >: R]: Pull[F, O, R2]
Short-hand for
(this: Pull[F, O, R2]).Short-hand for
(this: Pull[F, O, R2]). Used to assist with type inference. -
final
def
eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
equals(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
evalMap[F2[x] >: F[x], R2](f: (R) ⇒ F2[R2]): Pull[F2, O, R2]
Alias for
flatMap(r => Pull.eval(f(r))). -
def
finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( classOf[java.lang.Throwable] )
-
def
flatMap[F2[x] >: F[x], O2 >: O, R2](f: (R) ⇒ Pull[F2, O2, R2]): Pull[F2, O2, R2]
Applies the result of this pull to
fand returns the result.Applies the result of this pull to
fand returns the result.This method returns a new composed pull, which will do as follows:
- If
thispull succeeds with a resultrof type R, theffunction is applied tor, to build a new pullf(r), and the result pull starts running that new pull. The composed pull will terminate (or not) just as the new pullf(r)does. - Ifthispull fails or is interrupted, then the composed pull terminates with that same failure or interruption. - If evaluatingf(r)to build the pull throws an exception, the result is a pull that fails with that exception.The composed pull emits all outputs emitted by
thispull, and if successful will start emitting the outputs from the generated pull.This operation does not modify resource scope boundaries. The generated
postpull starts running on the same scope in whichthispull ended, and the composed pull will end on the same scope in whichpostpull does. -
final
def
getClass(): Class[_]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
def
handleErrorWith[F2[x] >: F[x], O2 >: O, R2 >: R](handler: (Throwable) ⇒ Pull[F2, O2, R2]): Pull[F2, O2, R2]
Allows to recover from any error raised by the evaluation of this pull.
Allows to recover from any error raised by the evaluation of this pull. This method returns a composed pull with the following semantics: - If an error occurs, the supplied function is used to build a new handler pull, and it starts running it. However, the pull cannot be resumed from the point at which the error arose. - If no error is raised, the resulting pull just does what
thispull does. -
def
hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
final
def
isInstanceOf[T0]: Boolean
- Definition Classes
- Any
-
def
lease: Pull[F, O, R]
Leases all resources that are currently open, canceling the lease at the termination of this pull.
-
def
map[S](f: (R) ⇒ S): Pull[F, O, S]
Maps the result of this pull with the
fmapping function.Maps the result of this pull with the
fmapping function.If
thispull ends in success with a resultr, then the functionfis applied to its resultr, and the imagef(r)is the result of the mapped pull. However, if the evaluation off(r)throws an error, the mapped pull fails with that error.Note: for some simple cases of Pull, the
mapfunction may be eagerly applied, or discarded, _before_ the pull starts being run.If
thispull terminates abnormally, so does the mapped pull. -
final
def
ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
final
def
notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
def
onComplete[F2[x] >: F[x], O2 >: O, R2](post: ⇒ Pull[F2, O2, R2]): Pull[F2, O2, R2]
Run
postafterthis, regardless of errors duringthis:Run
postafterthis, regardless of errors duringthis:- If
thispull terminates successfully, then its result is discarded and thepostpull is run. However thepostpull ends, be it in success, error, interruption, is how the combined pull ends.- If
thispull fails, thepostpull is run next. If thepostpull ends, fails, or is interrupted, that is how the combined pull ends. However, if thepostpull succeeds, then the combinedonCompletepull fails again with the error that was raised fromthispull.- If
thispull is interrupted, then thepostpull is never run and the combined pull ends with that same interruption. -
final
def
synchronized[T0](arg0: ⇒ T0): T0
- Definition Classes
- AnyRef
-
def
toString(): String
- Definition Classes
- AnyRef → Any
-
def
void: Pull[F, O, Unit]
Discards the result of this pull.
Discards the result of this pull.
If
thispull ends in success, its result is discarded and the _voided_ pull returns the unit()value. Otherwise, the voided pull just does the same asthispull does.Alias for
this.map(_ => ()). -
final
def
wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... ) @native()