Re: Left fold enumerator - a real pearl overlooked?

John A. De Goes schrieb:
Elsewhere, laziness can be a real boon, so I don't understand your question, "Why have laziness in Haskell at all?"
As I have written, many libaries process their data lazily (or could be changed to do so without altering their interface) but their interface can forbid application to data that is fetched from the outside world. Say you are used to 'map', 'filter', 'foldr' - you cannot use them on data fetched by the iteratee/enumerator approach.
Thank you for replying to this; it's good to see what features people would like to make iteratees more useful. Where did you get the idea that you can't use 'map'? IterateeGM is a Monad and Functor, so fmap is available for the resultant value. If you want to map over the elements of the stream, use the 'mapStream' function ('map_stream' in Oleg's writings). I never thought about writing a general iteratee fold because that's all iteratees are anyway; it's simple enough to make a foldl. It should be possible to write foldr for seekable resources by enumerating the stream backwards. That certainly wouldn't work for network I/O, unfortunately. Note that this is essentially the approach taken by lazy bytestrings, for example. There are other elements I'd want to address before adding this, however. There are also complications dealing with nested streams. I have some ideas, but the way forward is far from clear. filter should be fairly simple to implement with peek and drop. I'll look into it. Cheers, John

On Wed, 4 Mar 2009, John Lato wrote:
John A. De Goes schrieb:
Elsewhere, laziness can be a real boon, so I don't understand your question, "Why have laziness in Haskell at all?"
As I have written, many libaries process their data lazily (or could be changed to do so without altering their interface) but their interface can forbid application to data that is fetched from the outside world. Say you are used to 'map', 'filter', 'foldr' - you cannot use them on data fetched by the iteratee/enumerator approach.
Thank you for replying to this; it's good to see what features people would like to make iteratees more useful.
Where did you get the idea that you can't use 'map'?
What I meant was, that you cannot just use the functions you are used from Data.List. You need functions adapted to Iteratee. This also implies that all libraries written in terms of Data.List functions cannot be used as they are. Maybe it's a good time to review those libraries, whether they need lists at all, or whether they would also work with functionality that can be provided by Iteratees. The question, whether libraries should be bound to lists and Strings did already arise with ByteStrings. So Iteratees may be just one more reason to generalize the libraries.

On Thu, 2009-03-05 at 23:52 +0100, Henning Thielemann wrote:
On Wed, 4 Mar 2009, John Lato wrote:
John A. De Goes schrieb:
Elsewhere, laziness can be a real boon, so I don't understand your question, "Why have laziness in Haskell at all?"
As I have written, many libaries process their data lazily (or could be changed to do so without altering their interface) but their interface can forbid application to data that is fetched from the outside world. Say you are used to 'map', 'filter', 'foldr' - you cannot use them on data fetched by the iteratee/enumerator approach.
Thank you for replying to this; it's good to see what features people would like to make iteratees more useful.
Where did you get the idea that you can't use 'map'?
What I meant was, that you cannot just use the functions you are used from Data.List. You need functions adapted to Iteratee. This also implies that all libraries written in terms of Data.List functions cannot be used as they are. Maybe it's a good time to review those libraries, whether they need lists at all, or whether they would also work with functionality that can be provided by Iteratees. The question, whether libraries should be bound to lists and Strings did already arise with ByteStrings. So Iteratees may be just one more reason to generalize the libraries.
In most cases we can get the list version from a continuation based version. A continuation based version can also be used to implement an iterator version. Leaving aside the amount of work, I've been trying to think of how to do a iterator version at all for some libs. Specifically, my zlib binding. Currently the zlib package provides functions on lazy bytestrings: compress, decompress :: ByteString -> ByteString This hides all the complications of blocks and filling and draining buffers. However since it uses lazy bytestrings it is most naturally used with lazy io. The question is can I make an interface that also keeps the devotees of iterator based IO happy and also lets me implement the existing api above. I cannot see how to do it. Note that compress and decompress are pure. This is something that I want to keep. I don't want to go back to using IO for a pure operation like compression just for the sake of iterator IO. The problem of course is that while zlib compression is pure overall, there is an internal state thread. That must be threaded linearly. We cannot hand out a continuation that can be run multiple times. Lining up the zlib state thread with the memoising lazy list works perfectly. I cannot see how we do the same with an iterator interface. I'm not saying it cannot be done. On the contrary, I would like to see it done. Duncan
participants (3)
-
Duncan Coutts
-
Henning Thielemann
-
John Lato