3 ms·
> To put it another way, Haskell's had a great story around IO for 29 years, or longer than Java's been around. That is a tall claim. LazyIO has been problemat
by mavelikara 6y ago
> To put it another way, Haskell's had a great story around IO for 29 years, or longer than Java's been around.
That is a tall claim. LazyIO has been problematic in Haskell well into the 2010's until Iteratees became well-understood.
- mavelikara 6y agoCare to explain the downvote? From Oleg Kiselyov's 2012 paper Iteratees [1]: Lazy IO is so irresistible that it was added to Haskell despite the reservations of its inventors and the failure to develop good techniques for reasoning about its correctness [7, Sec 10.5]. However benign, reading is an observable side-effect, whose occurrence may have to be correlated with other side effects. Such correlations are crucial when performing IO over communication pipes, which is typical of web servers.3 As Launchbury and Peyton Jones feared, Lazy IO indeed "gives rise to a very subtle class of programming errors". We have seen deadlocks; mishandling of IO errors; running out of file descriptors and similar scarce resources; unpredictable, volatile and sometimes unbearably excessive use of memory. We illustrate the splendors and miseries of Lazy IO in §2. This is a very famous Haskell programer's opinion on the default IO in Haskell, and he quotes that one of the main creators of the language himself anticipated such problems [2]. Why downvote a comment in 2021 challenging the claim that "Haskell's had a great story around IO for 29 years"? [1]: http://okmij.org/ftp/Haskell/Iteratee/describe.pdf http://okmij.org/ftp/Haskell/Iteratee/describe.pdf [2]: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/state-lasc.pdf https://www.microsoft.com/en-us/research/wp-content/uploads/...
- tome 6y agoIteratees (nowadays pipes, conduit etc.) are based on functionality that was already there in 1992. They didn't add anything to Haskell. They're just libraries. Lazy IO has indeed always been bad but it wasn't the only part of Haskell's IO story.
- dllthomas 6y agoLazy IO is great where lazy IO is great! Long running processes handling lots of different requests, not so much, and that's made up an increasing amount of what people want to do. But for "open a file, chew through it, errors when consuming it might as well take down the process" nothing could be easier.
- mavelikara 6y agoWhat were the other options available in Haskell in 1992, besides Lazy IO, which made for a great IO story then? Please point me to code or papers from then because I am genuinely interested to learn.
- tome 6y agoReading and writing between handles and buffers, just like any other language. If you object specifically to the adjective "great" then, well, I don't think that was the operative point of the original comment.
- mavelikara 6y agoI object to both the use of “great” and the (needless, IMO) mention of Java in mrkeen’s comment.
- mrkeen 6y agoI might be naive, but I just assumed that I was still using lazy IO. I've used conduits before, and understand that pipes fit the same design space. But most of the time I just use read and write operations exposed by Bytestring, etc. My point is that since I like IO today, and I didn't think that laziness had been removed, then I probably would have liked IO back in the day.
- dllthomas 6y ago"Lazy IO" is things like `readFile :: FileName -> IO String`, where that String you get back secretly hides a thunk that will read more from the file when you evaluate it (even in pure code). The operations provided by `Data.ByteString` do not work like this; the ByteString you get back represents a buffer, and it has already been processed by the time the RHS of >>= starts executing. The operations provided by `Data.ByteString.Lazy`, on the other hand, do work like that; the ByteString you get back is a linked sequence of buffers, and some of those links might be thunks to go get the next bits of the ByteString for you. This is why a Data.ByteString.ByteString and a Data.ByteString.Lazy.ByteString are different types, and you can't just pass one where the other is expected (unless you've abstracted over it) - they're actually shaped differently.