@haskman I mean. Streams though.
@monad_cat @haskman sure! I recently wrote a lib for working with streams in Lean. Frankly, compared to writing one in Haskell, it was error prone pain in the ass. Exactly what @dpwiz is talking about. But yeah, it's a tradeoff, but it's not like one is more natural or easier to code with than the other. I do a lot of streaming so for me first class lazieness is something that I miss.
@monad_cat @jonn @dpwiz You only have to handle the complexity once and then push it into a module/library for everyone to use.
For example, you can use the free monad to stream in PureScript just the same way you would use the free monad in Haskell. The magic of implementing a stack safe eagerly evaluated free monad is buried inside the purescript-free library.
@haskman what do you mean by complexity here?
@dpwiz Code complexity. Code that exploits laziness is harder to understand and reason about.
@haskman I find the opposite is true. Is that complexity or difficulty an objective thing?
@dpwiz I don't know if your question is rhetorical.
@haskman Either your claim about "laziness (by default) is bad" is objective/universal and one of is wrong (and I, personally, would like to stop being wrong). Or it is subjective and there's nothing for us to argue about.
@dpwiz Okay, assuming your question was genuine - Let me play the argument out on both sides for a bit -
A predictable order of evaluation, especially in the presence of bottom and infinity, makes it easier to understand the code. So in my mind it's objective yes.
However, I suspect you are thinking of something like this - anyone would find writing `1+2` clearer than the machine instructions needed to load and add those numbers, even though the order of doing things is less specified in the mathematical notation. So it's objective the other way in your mind.
So perhaps it's subjective because it depends on the level you are looking at things from, which might be different for different people.
@haskman Thank you. I now wonder how a proper qualifier would like like.
It can't be "laziness is bad if you need performance" as there are some good algorithms that leverage laziness to get amortized speed-ups.
It can't be "laziness is bad if you need to analyze code" as there are cases where order is irrelevant (e.g. commuting operations).
🤔
@haskman But anyway, I think that questioning laziness is barking up the wrong tree. What we should strive for is not strictness, but a better tooling that will answer the challenges of performance and legibility "in the large".
Otherwise we're end up in competition with the other more established languages and their outgrown ecosystems instead of walking on our strong foot.
@dpwiz Laziness is not bad, it just trades off user friendliness. I personally like laziness, I like feeling smart when I tie the program up in knots and write seemingly impossible functional programs. But the fact is that code reviews in Haskell teams are harder than code reviews in PureScript teams. And it's an unnecessary cost because I'm yet to find a practical usecase where PureScript loses out to Haskell due to differing evaluation strategies.
@haskman Why do you even want to consider laziness at a review time? Without a profiler/benchmark data you can't point a finger at the expression and say "there's laziness in there, make it strict to go faster" on a hunch. It may as well go slower.
@haskman @dpwiz there is already a counterexample I provided: streams. In general, any structures you traverse from inside out are easier to write and understand with laziness. I thought that in another thread we agreed that there are no "natural" evaluation order. (As I side note: I think that cognitively laziness is easier because humans glance, not drill, but that's a topic for behavior scientists to figure out).
@haskman I'm talking about data strucutres, not algorithms. The data structure I'm talking about, namely, is "stream".
In Haskell it's just `Cons a (Stream a)` and you write code (algorithms) over it as normal. In Ocaml it's `type 'Cons of 'a * (unit -> 'a stream)`.
Same goes for zippers.
I'm not smart enough to know fancy algorithms, but if functions over possibly infinite datums, you can imagine how explicit thunking makes things worse.
https://github.com/lurk-lab/straume/blob/main/Straume/Chunk.lean all of this machinery can be avoided entirely with laziness, for example.
@dpwiz@qoto.orgThere are always tradeoffs. However, in my experience the complexity doesn't seem worth it in production code.