Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I find all those streaming I/O libraries (and lazy bytestreams as well) to be more neat-looking than useful: they can produce slightly cleaner code when used for basic tasks (such as those in examples), are fun to play with, and generally seem nice at first. But once you have a bunch of dependencies with their own (byte)string/text types, errors/exceptions, and ways to do I/O, all of which should be combined and work together, those become rather annoying. Additionally, it becomes easier to shoot yourself in the foot (which is mentioned in the alternative title, but doesn't seem to be expanded on much) -- say, by closing a Handle or even merely not draining the input before proceeding with other I/O, if the outside system expects you to.

At the same time, it's not a big deal to handle potentially infinite streams with strict I/O and explicit chunks.

I imagine it is possible to build projects around such libraries, possibly wrapping all the other I/O into it. Similarly to how in principle it's possible to unify all the error-yielding functions, and those working with text and/or byte streams. But I guess it doesn't happen often.



> Additionally, it becomes easier to shoot yourself in the foot (which is mentioned in the alternative title, but doesn't seem to be expanded on much) -- say, by closing a Handle or even merely not draining the input before proceeding with other I/O, if the outside system expects you to.

Hmm, I find the opposite - iteratee-style streaming libraries are pretty much the only way you can implement something like "open this file and transform it in this way" as a library function and ensure it gets used safely, because the stream can be responsible for resource management.

(I'm opposed to Haskell-style implicit laziness though, I agree with strict and explicit chunking being the way to go).

> But once you have a bunch of dependencies with their own (byte)string/text types, errors/exceptions, and ways to do I/O, all of which should be combined and work together, those become rather annoying.

Sure. I think the answer to that is that iteratees are pretty foundational and should be built into the language, in the same way that e.g. monad is not just a library type but something that's fundamentally part of the "platform" and maybe even the standard library. Efforts like the "Haskell platform" help us move in that direction.


There's some completely different programming patterns that are useful when dealing with streams. Streams really come into their own within DAGs. DAGs are to streams what module structures are to programs. You organize streams within a DAG, and can manage different use cases and goals with different branches. Exceptions can be handled flexibly if they are turned into data for the stream. Same goes for configuration.


> it becomes easier to shoot yourself in the foot (which is mentioned in the alternative title, but doesn't seem to be expanded on much) -- say, by closing a Handle

lazy I/O (such as file reads) is suspect and even bad, but laziness + IO (or something like it) is a great way to stream from an API: http://blog.vmchale.com/article/lazy-io

Makes it possible to transcode for one. Basically makes streaming "compose" nicely - bzip2 and lzip otherwise have very different ways of streaming! And one would have to line a lot of things up.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: