6 ms·
Thinking with Lazy Evaluation
- tempodox 11y agoFTA: Control flow can be manipulated as data. That's an interesting perspective, I've never seen it that way before. I would love to learn more about this, as a non-Haskeller.
- agumonkey 11y agoI see functions as tiny stepping gears and composition as the mental act of assembling these mathematical pieces of geometry.
- tempodox 11y agoAs far as that goes, you can do it in Lisp or ML, too. But Haskell's lazy evaluation adds a nontrivial twist to it that I haven't fully grokked yet.
- jjaredsimpson 11y agoI understood Haskell once I internalized the actual purpose of non-strict semantics. Abstractly your program is a tree rooted at main. In a language like C you concentrate on building trees knowing that you are going to touch every node. So you are trying to design small trees that have good execution semantics as well as being correct in the problem solving domain. You have to address the problem at 2 levels. Because C is strict every function you call will be evaluated before it can return some result. Haskell is different you can build any tree you like because a node will only be evaluated if its result is required for the current context. You are free to work with models of data like "the integers" or "all possible game states". Concretely in C if you wanted to find the smallest positive integer that satisfies some property P you would write something like for (int i=1; ; i++) if (P(i)) return i; This is a single node in your program tree which modifies a variable until a condition is met. In contrast in Haskell you might do something like find P [1..] I would interpret this as find operating on an infinite lazy tree and discarding the infinite tail list (which is an infinite computation) once the result is found. Applying this simple example, in Haskell you aren't concern with limiting the shape of your program's tree. You build the correct model for your program regardless of constraints like infinite lists or terminating searches early. You just allow non-strict evaluation to process your input data because you will never have to strictly generate an infinite integer list before scanning it. At root non-strict semantics is just a reversal of the order of reduction of expressions.
- agumonkey 11y agoAm I misguided to think that strict / lazy has some relation between push / pull effects in other systems (GUI, parsing) ? Beautiful comment btw.
- tome 11y agoThat sounds like a good intuition to me. Strict is like push, because it gives you the result as soon as it's ready. Lazy (or perhaps more precisely non-strict) is like pull because you have to go and ask for the result.
- agumonkey 11y agoYes, and after years of struggling to find which should prevail, I recently heard the term of backpressure (used in reactive GUI IIRC) to be able to reason about things in both direction. Is there a middle ground for evaluation strategies ? Right now one can for strictness (in Haskell) or lazyness (in ml) but I never found a 'theory' about both.
- jessaustin 11y ago...backpressure (used in reactive GUI IIRC)... And unix pipes, and node.js streams... Your intuition about a middle ground is interesting. Perhaps one of javascript's derivative languages could come up with some syntax to make using this more intuitive, because let's face it node.js streams would be easier to use if there were some way of plumbing them together that didn't look like Java from 1999.
- agumonkey 11y agoRight any streams. Also this https://github.com/dominictarr/pull-stream#transparent-backpressure--laziness https://github.com/dominictarr/pull-stream#transparent-backp... article says reducers are related too.
- buttproblem 11y ago
- irickt 11y ago“Monads turn control flow into data flow, where it can be constrained by the type system.” Oleg Kiselyov quoted in the paper "Monads are Trees with Grafting" by Dan Piponi
- BlanketLogic 11y agoNice. But Laziness with I/O is not trivial at all.
- dllthomas 11y agoThat's true. An obvious solution is "keep IO out of your lazy computations", which hopefully you can get some language help with. There are some attempts at other approaches as well.
- LukeHoersten 11y agoHaskell has some great solutions for lazy IO: io-streams or pipes for example. Check them out! It's a great way to code IO.
- BlanketLogic 11y agoYes. Conduits and iteratees too, for that matter. And I believe, there was some talk about "Machines", which I did not understand at all. Am not sure what is the current status of that approach. I thought conduits and io-streams are preferred over pipes.
- codygman 11y agoAs I understand it in the Haskell community right now. 1. Pipes | Conduit 2. io-streams (perhaps not in 1 only because of a lack of popularity and it is new) 3. Iteratees (have some issue Pipes/Conduit do not which I can't recall) Not sure where Machines comes in here.
- LukeHoersten 11y agoio-streams is built specifically for IO and is in the IO monad. This allows for performance benefits as well as simplified API like using normal IO functions for error and resource handling (ex: `bracket` can be used)
- cpursley 11y agoNeat. If you're a Ruby developer check out rlet - a rspec-like let for lazy evaluation: http://github.com/hosh/rlet http://github.com/hosh/rlet
- jmount 11y agoR has lazy evaluation (but only at function arguments). That makes it an easy place to play with some of the effects of lazy evaluation (but not get too bogged down with issues like IO).
- anon4 11y agoOne thing that bothers me is, can I rely on the compiler making those optimisations? Which ones are guaranteed for me? Those are sort of important considerations, because it can mean the difference between a linear fibs and a quadratic fibs, or an O(nlogn) sort and a O(n²) sort.