Hacker News new | ask | show | jobs
by yoyohello13 1602 days ago
Is Laziness really that big of an issue in practice though? Admittedly, I'm pretty new to Haskell. I've done a few CLI programs and one little web app using Yesod, and the fact that Haskell is lazy by default has never come up.
3 comments

It comes up when you're dealing with large amounts of data; you go to evaluate the value of a function and it crashes because the stack limit was exceeded. (Ghc changed some things awhile back so that it just allocates more memory now instead of crashing, but still it can cause performance/memory use issues if what looks like just an integer is actually just pointing to an unevaluated thunk pointing to megabytes of data.) Laziness is also annoying when trying to get parallel code to actually run in parallel instead of having expensive computations deferred to whenever the consumer evaluates the value of something.

Laziness does have real benefits sometimes though. It's nice to be able to define infinite data structures, for instance.

My experience:

For one, it makes reasoning about runtime (as in "how long") harder: E.g. an innocent looking "take 5" might be what actually executes half of the code you've written... which is also harder to reason about than if it would be "all of it". This can also make debugging harder: Values are only evaluated when they are needed, and a "value" itself may not be just, say, a single number, but a complex data structure consisting of many values, so that "evaluated" has many different stages between "a thunk, not evaluated at all" and "weak head normal form". So code does not get executed when you wrote so in your program, but potentially much much later. Semantically that should not make a difference (the results should be the same), but when you want to debug program flow...[1]

You can see how "thunks" in general add a certain dimension to everything you do. Throw in interaction with garbage collection, and things aren't always obvious in resource usage.

Also, there is maybe an argument that if you have infinite data structures that you only tend to evaluate partially (which is what makes laziness really fun, actually), then accidentally trying to fully evaluate such a data structure makes your program not terminate anymore. But I'm not sure how that's really a problem coming from laziness. Laziness allows you to handle infinite data structures in the first place, mishandling them is not much different than accidentally writing an infinite loop in a strict language, in my opinion.

That being said, I still enjoy writing Haskell very much when I get to. It makes me feel much more productive, and I do lament having to use other languages at work. I must say using Haskell was always on private projects, and I have never tried doing so in a team, though.

[1] On the flip side, I find the pureness and strictness of Haskell to make debugging easier, or just less necessary.

It can sometimes be an issue in certain "Gotta go fast" scenarios, where you'd otherwise be able to reason quite confidently about program behaviour with a strict language.