Just enabling strictness everywhere in Haskell isn't just inherently better. Laziness is actually quite good (and the OP even says this to an extent). It's more nuanced than it seems.
Just enabling strictness everywhere in Haskell isn't just inherently better. Laziness is actually quite good (and the OP even says this to an extent). It's more nuanced than it seems.
(Tree = Leaf !Int | Node [Tree]))
and if you really need a lazy int in there, delay it yourself using partially applied functions.From what I remember to get around this one would use a type class to define a data structure's operations, and then provide specific implementations of that data structure for specific strict data types. But that is more complicated than just having the compiler apply strictness everywhere.
In all I guess I'm not disagreeing with you at all, I just wanted to provide a bit more context and get some more use out of that book.
For large amounts of data in an immutable structure, laziness is pretty much essential. The theory behind strict-by-default is that most of the time, you are not dealing with large amounts of data; even if you have pointers to large data, or pointers to pointers of large data. Even though laziness is vital to a pure language, you only need to use it in a relatively small number of places.
For example a strict function on a strict persistent list that swaps the head of the list doesn't have to copy the entire tail of the list.
The thing that laziness enables is short-circuiting, so e.g. a fold over the list can bail out early if necessary. But this is actually a minority of use cases for large data, since we often bound the size of data structures with something like a `take n` function for some integer n, which only processes n elements in a strict language.