Library
Module
Module type
Parameter
Class
Class type
include Bare_sigs.Seq_e.S
This is similar to Stdlib
.Seq.S.t
but the suspended node is a result.
Consequently, the sequence of elements may be interrupted by an error. Specifically, there are two possible kinds of sequences:
- interrupted sequences where one of the suspended nodes is not returned and an
Error _
is produced instead, and - whole sequences where all the suspended nodes are actually returned inside an
Ok _
.
All the traversors below treat sequence interruption as an error that is returned as is.
Also note that nodes are suspended by a continuation rather than a lazy block. As a result, different traversals of the same sequence can lead to repeated evaluations of the same elements, or distinct sets of elements, or even a different kind of sequence. E.g., if a suspended sequence fails or succeeds depending on the content of a reference.
This is not recommended. You should use deterministic sequences that do not depend on state. Or you should use one-shot sequences that are used once and then never again. The documentation of this module is written assuming you adhere to these constraints.
val empty : ('a, 'e) t
A whole sequence of zero elements.
val return : 'a -> ('a, 'e) t
return x
is a whole sequence containing the single element x
.
return_e (Ok x)
is a whole sequence containing the single element x
. return_e (Error e)
is a sequence immediately interrupted by the error e
.
val interrupted : 'e -> ('a, 'e) t
interrupted e
is a sequence immediately interrupted by the error e
.
val nil : ('a, 'e) node
nil
is the node forming the empty sequence.
cons x s
is the sequence containing x
followed by s
. It is a whole sequence if s
is.
cons_e (Ok x) s
is the sequence containing x
followed by s
. It is a whole sequence if s
is.
cons_e (Error e) s
is a sequence immediately interrupted by e
.
append s1 s2
is a sequence s
. If s1
is a whole sequence then s
is composed of all the elements of s1
followed by s2
. If s1
is an interrupted sequence then s
is indistinguishable from s1
.
s
is a whole sequence if both s1
and s2
are.
first s
is None
if s
is empty, it is Some (Error e)
if s
is immediately interrupted by e
, it is Some (Ok x)
where x
is the first element of s
otherwise.
Note that first
forces the first element of the sequence, which can have side-effects or be computationally expensive. Consider, e.g., the case where s = filter (fun …) s'
: first s
can force multiple of the values from s'
.
fold_left f init seq
is
- if
seq
is a whole sequence, thenOk x
wherex
is the result of foldingf
over all the elements ofseq
starting withinit
, or - if
seq
is interrupted byError e
, thenError e
.
Note that, as with all other traversors below, if the sequence is interrupted, all the side-effects of f
on the successful prefix of seq
have already been applied before the traversal returns Error _
.
fold_left_e f init seq
folds f
over the elements of seq
with an accumulator set at init
. It stops traversal (returning Error _
) if f
returns an Error _
or if the sequence is interrupted. Otherwise it returns Ok _
.
This function does not discriminate between interruption and traversal errors. The fold_left_e_discriminated
provide such a distinction.
val fold_left_e_discriminated :
('a -> 'b -> ('a, 'f) result) ->
'a ->
('b, 'e) t ->
('a, ('e, 'f) Either.t) result
fold_left_e_discriminated f init seq
is the same as fold_left_e
but errors from f
are wrapped in Right
whilst interruptions in seq
are wrapped in Left
.
fold_left_e_discriminated f init seq
is equivalent to
fold_left_e
(fun acc item ->
f acc item |> Result.map_error (fun e -> Either.Right e))
init
(s |> map_error (fun e -> Either.Left e))
fold_left_s f init seq
is a promise that resolves to
- if
seq
is a whole sequence, thenOk x
wherex
is the result of foldingf
over all the elements ofseq
starting withinit
, or - if
seq
is interrupted byError e
, thenError e
.
Note that if it returns Error _
, the side-effects of f
on previous elements have already been applied anyway.
The elements are traversed sequentially. Specifically, a node's suspension is called only when the f
-promise of the previous node has resolved. Thus, there might be yielding in between suspensions being called.
fold_left_es f init seq
is a promise that resolves to
- if
seq
is a whole sequence andf
-promises always resolve successfully, then the result of foldingf
over all the elements ofseq
starting withinit
, - otherwise,
Error _
with the error that interrupts the sequence or with an error returned byf
, whichever happens first.
The elements are traversed sequentially. Specifically, a node's suspension is called only when the f
-promise of the previous node has resolved. Thus, there might be yielding in between suspensions being called.
val fold_left_es_discriminated :
('a -> 'b -> ('a, 'f) result Lwt.t) ->
'a ->
('b, 'e) t ->
('a, ('e, 'f) Either.t) result Lwt.t
fold_left_es_discriminated f init seq
is the same as fold_left_es
but errors from f
are wrapped in Right
whilst interruptions in seq
are wrapped in Left
.
fold_left_es_discriminated f init seq
is equivalent to
fold_left_es
(fun acc item ->
let+ r = f acc item in
Result.map_error Either.right r)
init
(s |> map_error Either.left)
iter f seq
is fold_left (fun () x -> f x) () seq
iter_e f seq
is fold_left_e (fun () x -> f x) () seq
val iter_e_discriminated :
('a -> (unit, 'f) result) ->
('a, 'e) t ->
(unit, ('e, 'f) Either.t) result
iter_e_discriminated f seq
is like iter_e
but the errors from f
and seq
are kept separate.
iter_s f seq
is fold_left_s (fun () x -> f x) () seq
iter_es f seq
is fold_left_es (fun () x -> f x) () seq
val iter_es_discriminated :
('a -> (unit, 'f) result Lwt.t) ->
('a, 'e) t ->
(unit, ('e, 'f) Either.t) result Lwt.t
iter_es_discriminated f seq
is like iter_es
but the errors from f
and seq
are kept separate.
iter_p f seq
is a promise p
.
- If
seq
is a whole sequence, thenp
resolves toOk ()
once all the promises created byf
on the elements ofseq
have resolved. - If
seq
is interrupted byError e
, thenp
resolves toError e
once all the promises created byf
on the elements of the successful prefix ofseq
have resolved.
Note that the behaviour for interrupted sequences is in line with the best-effort semantic of Lwtreslib.
There is no iter_ep
in Bare
. The reason is that there can be two sources of failures and there is no satisfying way to combine failures for the caller.
map f seq
is a sequence feq
.
- If
seq
is a whole sequence, thenfeq
is a whole sequence where the elements are the result of the application off
on the elements ofseq
. - If
seq
is an interrupted sequence, thenfeq
is a sequence interrupted byError e
where the elements of the successful prefix are the result of the application off
on the elements of the successful prefix ofseq
.
map_error f seq
is a sequence feq
.
- If
seq
is a whole sequence, thenfeq
is the same whole sequence. - If
seq
is an interrupted sequence, thenfeq
is a sequence interrupted byError (f e)
where the elements of the successful prefix are the elements of the successful prefix ofseq
.
map_e f seq
is a sequence feq
.
- If
seq
is a whole sequence and iff
is successful on all the elements ofseq
, thenfeq
is a whole sequence where the elements arex
whereOk x
is the result of the application off
on the elements ofseq
. - Otherwise
feq
is a sequence composed of elements ofseq
mapped byf
and interrupted byf
returningError
or byseq
's interruption (whichever comes first).
There is no map_e_discriminated
because the result of a map*
is a sequence (t
) and so any error (even from f
) is, in essence, an interruption of the resulting sequence.
If you need to apply such a distinction and you are ready to deal with the resulting Either.t
-interruptible sequence, you can arrange this manually using map_error
and Result.map_error
.
A similar remark applies to the other combinators below.
filter f s
is a sequence of the same kind as s
with only the elements for which f
returns true
.
filter_e f s
is a sequence that is interrupted like s
or by f
being unsuccessful (whichever comes first) or whole (if neither cases apply). Whichever is the case, the elements of the resulting sequence are the elements of s
for which f
returns Ok true
.
filter_map f s
is a sequence of the same kind as s
where the elements are transformed by f
(when it returns Some _
) or dropped (when it returns None
).
filter_map_e f s
is a sequence that is whole or that is interrupted in the same way as s
(if it is) or that is interrupted by f
(if it happens). Whichever the case, the elements of the sequence or the successful prefix thereof are transformed by f
(when it returns Some _
) or dropped (when it returns None
).
val unfold : ('b -> ('a * 'b) option) -> 'b -> ('a, 'e) t