4 ms·
perhaps a dumb question, but why does laziness imply boxing? or does 'boxing' in haskell mean something other than 'embed a simple bit of data in a fancy thing
by bananapub 2y ago
perhaps a dumb question, but why does laziness imply boxing? or does 'boxing' in haskell mean something other than 'embed a simple bit of data in a fancy thing on the heap'?
- benreesman 2y agoA dramatic over-simplification is that a lazy value referenced by some continuation/thunk is hard to stack allocate in-situ. Now GHC does stack allocate, but it’s hard to count on without really aggressive hinting.
- the_duke 2y agoFunnily enough Rust supports exactly that pretty well with async. An `async {}` block is not evaluated, but converted into a generator/state machine that lives on the stack, and that has to be advanced by calling a poll method. You can move it to the heap , but that does not happen automatically. Sharing of values is obviously much more awkward due to mutability and no automatic cloning though.
- benreesman 2y agoI know how it works though I remain unconvinced that rustc is dealing with the same scope of problem as GHC in the general case. But to be clear, anyone with the username the_duke is probably really cool, and you clearly know your stuff as well as having style, so count me as a fan.
- bananapub 2y agoah, right, laziness can cause the control flow to become extremely complicated - makes sense, thanks!
- benreesman 2y agoAlso true! And in very real sense literally what I meant. But not so much in the conditional branch sense of the phrase “control flow”. More like, I’ve got a bunch of references and one of them is a reference to a function I might evaluate, damn, I need that reference and the transitive closure of everything it knows about, all of which are probably on the heap.
- zozbot234 2y agoThe proper name for this is a "space leak". Also known as: "you wanted a banana, but what you got was a gorilla holding the banana and the entire jungle". This is of course pretty much the opposite of low-level "performance" - and it's also the kind of problem that tracing garbage collection was actually designed to address when first developed.
- benreesman 2y agoFake news and FUD and other balderdash. A space leak, much like any memory leak is when you or the compiler or the runtime or whoever misplaces such reference. GHC having a closure in scope in no way immediately means there is a space leak. Plenty of Haskell code that compiles to thunks will run all day in an amortized fixed-size heap. Much like Erlang, which is what Joe Armstrong had designed before he said the thing about jungles you’ve quoted. And it is in no way difficult or even really rare to drop an Arc in a table and leak all over the place. Rust has all the same computer science problems as anything else. Full stop.
- throwaway17_17 2y agoI seem to be missing the implication as well. I am under the impression that Haskell relies on boxed values primarily due to its parametric polymorphism. There is a Simon Peyton Jones talk somewhere discussing the acrobatic GHC requires for the type theory to deal with unboxed types and their implicit requirement for an alternative Kind at the type level. The laziness as a default just makes boxing closure values a sensible default, when the type system requires the boxing of everything in general.
- benreesman 2y agoOn everything from the JVM to GHC to v8 there is a critical distinction between the semantics of a boxed type and the practical outcome on the gear. Every managed language runtime done by pros (and those all are, I should have said the CLR too) will quietly unbox in all the easy cases and some of the hard ones. Parametric polymorphism is kind of orthogonal to that. It’s related I guess. It can involve some kind of runtime dispatch, but usually that gets JITed or inlined or whatever unless you really insult the compiler. And even full frontal invokedynamic it’s still like, is it in the BTB and the I-cache? Ok well we’re still doing business.