michaelt / streaming

An optimized general monad transformer for streaming applications, with a simple prelude of functions
BSD 3-Clause "New" or "Revised" License
104 stars 11 forks source link

hoist doesn't seem to play nicely with chunksOf #27

Closed ivan-m closed 7 years ago

ivan-m commented 7 years ago

(Probably other functions as well, but this is where I found it.)

Let us take a completely ridiculous example as a motivator, running this all in ghci.

λ> import                Streaming
λ> import qualified Streaming.Prelude as S
λ> let intEither :: Int -> Either Int Int; intEither n | even n = Left n | otherwise = Right n

If I get the effects out first and then get chunks, it works as expected:

λ> S.print . mapped S.sum . S.chunksOf 3 . S.effects . S.partitionEithers . S.map intEither $ S.each [1..10]
9
16

(and indeed, 1 + 3 + 5 == 9, 7 + 9 == 16).

However, to be able to do the chunks first (because I may be wanting to use the first part of the Stream for something):

λ> S.print . mapped S.sum . S.effects . hoist (S.chunksOf 3) . S.partitionEithers . S.map intEither $ S.each [1..10]
1
3
5
7
9

Now the chunking seems to only take one item at a time.

I'm not sure if the fault here is with chunksOf or splitAt, as I'm still trying to work out how to do the same thing with splitAt (as its type doesn't play well with hoist or embed).

ivan-m commented 7 years ago

It appears that hoist doesn't like running any monad transformer: I tried converting Stream (Of a) (StateT s m) r to Stream (Of a) m r with hoist (flip evalStateT initS) and it was run individually on each monadic step (so the state did not accumulate).

ivan-m commented 7 years ago

The same applies to conduit, so this may be a fundamental limitation of hoist.

I'll see if I can adapt how conduit does it to Streams.