4 ms·
A few minor corrections > Simon Peyton Jones is reported to have said that lazy evaluation has been kept "to keep us honest about side effects" Rather, one of
by tome 3y ago
A few minor corrections
> Simon Peyton Jones is reported to have said that lazy evaluation has been kept "to keep us honest about side effects"
Rather, one of the main benefits of laziness was to force purity and thereby to instigate the development of typed effects. By contrast, the reason that laziness has been "kept" is simply that switching to strictness now would break (almost) all Haskell programs!
> lazy evaluation comes at a pretty extreme performance cost
Not really. Haskell's implementation of laziness is very high performance and the compiler can easily determine when creating thunks is not necessary. The reason that lazy evaluation leads to performance problems is that programmers don't know how to use it correctly. Whether that's the fault of the language or the programmers is up for debate.
- logicchains 3y ago>The reason that lazy evaluation leads to performance problems is that programmers don't know how to use it correctly It's because it's objectively harder to reason about performance with lazy evaluation as performance becomes non-local. You can no longer reason about a function's performance just by looking at its body, instead you have to know the nature of the inputs passed to it (whether they're thunks or materialised values). Each single uses of lazy evaluation also imposes a latency overhead as the thunk/value must be behind a pointer. Yes the compiler can remove unnecessary thunks, but that's "unnecessary" in the sense of "unnecessary given the semantics of the program", not "unnecessary given the problem the program's trying to solve". I.e. lazy by default will generally result in someone writing code that's lazier than necessary unless they're very careful with annotating to the compiler everywhere laziness isn't needed.
- deleted 3y ago[deleted]
- slacknatcher12 3y ago> It's because it's objectively harder to reason about performance with lazy evaluation as performance becomes non-local. This is off-repeated, but has two interpretations. If you mean performance as in number of steps needed to reduce an expression, lazy evaluation is superior to strict evaluation. If you mean the indirection needed to access a thunk, well someone -- either the producer (strict) or the consumer (lazy) -- had to do that anyways. If GHC can determine that the demand for the value is strict, it won't generate the thunk in the first place. Instead it will provide a specialize calling convention via the worker/wrapper transform, which is standard. On the un-optimized case we still have dynamic pointer tagging (which is a transgression on the T of the STG machine) which serves as a tag to check whether we are dealing with a value or a thunk quickly. So if by non local performance you mean the indirection, modern GHC shows that is not true. If you means that space leaks are a non-local property and they affect performance, well you are sort that right. But as with all programming, we have defensive patterns against that. There are 2 types of space leaks: liveness leaks and strictness leaks. Only the first one are a non-local property, ie the appear as a consequence of the composition of different code pieces. But given the default purity of Haskell, those can only appear on long lived data references with are syntactically marked by: - IORef, MVars, TVars - get/put pairs over a state environment So what you do is to specify in the types that values stored on those environments are to be evaluated before being stored, so references don't leak. I speak about this on this https://epicandmonicisnotiso.blogspot.com/2023/04/how-to-avoid-correctness-space-leaks-on.html https://epicandmonicisnotiso.blogspot.com/2023/04/how-to-avo... and how to specify the a specific evaluation level on the types at here https://epicandmonicisnotiso.blogspot.com/2023/04/presenting-data-forced-alternative-to.html https://epicandmonicisnotiso.blogspot.com/2023/04/presenting... although that library has changed a lot to enforce the invariants.
- JonChesterfield 3y agoThis reply neatly captures that functional programming tends to consider performance/efficiency in terms of number of reductions. Sadly other programmers tend to view it as wall clock time and the two don't correlate very well.
- slacknatcher12 3y agoI just gave a list of possible meanings of what parent said. Only one of them is the numbers of reductions.
- kerkeslager 3y agoSadly? If a client comes to me and says one of the parts of their application was slow, and I come back to them saying I lowered the number of reductions with zero change in the wall clock time, they'll fire me, and rightly so.
- rovolo 3y agoTo be nitpicky, wall clock time isn't the same as CPU time or power draw. You can increase efficiency at the same time as you increase wall clock time because they aren't necessarily the same metric.
- foldr 3y agoI think you're overcomplicating this. In a language with lazy evaluation, you can't know what gets evaluated without looking at the whole program (in the worst case). It's in that sense that performance becomes non-local. Here's a simple specific example. Take the Haskell expression [1..n], for some big n. There is no general answer to the question "what would be the performance implications of replacing [] with [1..n]" – it depends on the context of []. In a strict language, you can say (roughly at least) that replacing [] with [1..n] will add at minimum a certain number of extra CPU cycles and a certain amount of additional allocation. This kind of reasoning is pretty rough and ready, but it is accurate enough to be useful for reasoning about performance in practice. I note that Simon Peyton-Jones has said these exact words in a public talk: "Laziness makes it much, much harder to reason about performance." I think it's extremely unlikely that he's mistaken or confused on this point.
- chriswarbo 3y ago> By contrast, the reason that laziness has been "kept" is simply that switching to strictness now would break (almost) all Haskell programs! Also, laziness is a big part of why Haskell exists in the first place. "Strict Haskell" would arguably feel more like ML, Agda, Idris, etc. than (lazy) Haskell. In which case, just use one of those; they're also decent languages ;)