Reputation: 41909
Why does the following output []
?
λ: >runConduitPure $ yieldMany [1..2] .| leftover 5 .| sinkList
[]
I naively expected it to return: [1,2,5]
per leftover's docs:
Provide a single piece of leftover input to be consumed by the next component in the current monadic binding.
Upvotes: 1
Views: 232
Reputation: 12749
We must make a distinction between the composition of Conduit
s with >>=
, and with .|
.
With >>=
, we are sequencing the actions of two Conduit
s that share a common input and a common output stream.
With .|
, we are connecting the output stream of one Conduit
to the input stream of another.
The leftover
function pushes a value into the current position of the current Conduit
's input stream, making it available to other Conduit
actions connected to the same input stream (with >>=
). It does not yield
anything into the current Conduit
's output stream, which is why sinkList
produces the empty list in your example.
If you want to see the effect of leftover
, you must perform the sinkList
where it can access the same input stream as the leftover
:
runConduitPure $ yieldMany [1..2] .| (leftover 5 >> sinkList)
This produces [5, 1, 2]
(not [1, 2, 5]
), because the leftover
pushes the 5
into the input stream before the 1
, and 2
, have been consumed.
If we add an await
before the leftover
:
runConduitPure $ yieldMany [1..2] .| (await >> leftover 5 >> sinkList)
then we get [5, 2]
because we consume (and discard) the 1
before doing the leftover
.
We could also yield
from our leftover
Conduit
, which will push a value into the output stream to be consumed by another Conduit
composed with .|
:
runConduitPure $ yieldMany [1..2] .| myLeftoverConduit .| sinkList where
myLeftoverConduit = do
leftover 5
l <- sinkList
yield l
yield [42]
produces [[5, 1, 2], [42]]
because we yield
ed the result of sinkList
(a list), and then yield
ed [42]
(also a list). The downstream sinkList
then makes a list of these two values.
Upvotes: 6