Kevin Meredith
Kevin Meredith

Reputation: 41909

Understanding 'leftover' from conduit

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

Answers (1)

pat
pat

Reputation: 12749

We must make a distinction between the composition of Conduits with >>=, and with .|.

With >>=, we are sequencing the actions of two Conduits 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 yielded the result of sinkList (a list), and then yielded [42] (also a list). The downstream sinkList then makes a list of these two values.

Upvotes: 6

Related Questions