Gabriella439 / pipes

Compositional pipelines
BSD 3-Clause "New" or "Revised" License
487 stars 72 forks source link

add unfoldr #150

Closed michaelt closed 9 years ago

michaelt commented 9 years ago

I was writing a replica of Pipes.Prelude for the obvious variant of FreeT ((,) a) m r and it was irritating that this could not be found. See the dumb comments on the parallel function at

https://github.com/michaelt/streaming/blob/c3ee6d89c2a019a1b198b73edbd37e4d52cf3f3d/Streaming/Prelude.hs#L715

and the corresponding comments on 'next' and 'uncons'

https://github.com/michaelt/streaming/blob/c3ee6d89c2a019a1b198b73edbd37e4d52cf3f3d/Streaming/Prelude.hs

It is a slightly different issue, but it was seeming to me that it might be easy to get 'interoperation' for the Producer, Conduit.Source, IOStreams.InputStream types if they all exported a 'next' or 'uncons' . The other natural way of 'translating' is via a natural fold or church encoding. But the 'fold' concept is in all these libraries understandably the strict-left-fold. conduit and io-streams already export an unfoldM that corresponds to this unfoldr (but lacking a final return value and thus using maybe). I was thinking of trying to convince all the libraries to export an uncons or next so that they could be unfolded into each other.

michaelt commented 9 years ago

The link to Streaming.next and uncons was supposed to be

https://github.com/michaelt/streaming/blob/c3ee6d89c2a019a1b198b73edbd37e4d52cf3f3d/Streaming/Prelude.hs#L451

michaelt commented 9 years ago

I probably didn't make it clear, but my scheme is, if possible, to convince the other libraries to export an uncons so their unfoldM's match, and a hopefully a next to match the above function. It is easy to define

 IOStreams.uncons :: InputStream a -> IO (Maybe (a,InputStream))
 IOStreams.next :: InputStream a -> IO (Either () (a,InputStream))

but I'm not sure unfolding from them in this way will take the best advantage of the implementation with IORefs A completely unified idiot-simple scheme would require a pipes

uncons = liftM (either (const Nothing) Just . next

for convenient use with the unfoldMs of the other libraries, and perhaps a next-using unfold for conduit.

Gabriella439 commented 9 years ago

Looks good to me! It's also worth pointing out that this is how you would encode a Producer using stream fusion:

Producer a m r  ~  exists s . (s, s -> m (Either (a, s) r))