I’ve been pointed to https://github.com/ghc-proposals/ghc-proposals/pull/35 where this was debated a few years ago. With much of the same arguments as today.

Simon Marlow said

making an unboxed tuple binding lazy by default seems to be intuitively the wrong choice. I guarantee I would get tripped up by this! Giving unboxed tuples an implicit bang seems reasonable to me.

I can share that I got tripped by it. And so were other members of my team.

That being said, Richard seemed to feel rather strongly about this one. Richard, do you still agree with your then position that let (#x, y#) = … being a lazy pattern (hence implicitly boxes the pair) is the right semantics?


On Fri, Aug 28, 2020 at 8:26 PM chessai <chessai1996@gmail.com> wrote:
Arnaud,

I have dealt with this in the past and find the laziness extremely counterintuitive and never wanted. Every time I have let-bound an unboxed tuple, I have never wanted that boxing to occur. Perhaps there is a good reason this is the case but I wish it would change.

On Fri, Aug 28, 2020, 08:26 Spiwack, Arnaud <arnaud.spiwack@tweag.io> wrote:

Hi Carter,

We are using let !(#x,y#) = … actually. Having the strict behaviour is not particularly difficult. You can even use case … of (#x, y#) ->… directly, it’s not too bad. My complaint, as it were, is solely about the potential for mistakes.


On Fri, Aug 28, 2020 at 3:20 PM Carter Schonwald <carter.schonwald@gmail.com> wrote:
Have you tried using do notation for bindings you want to keep strict, with Eg the identity monad?  That doesn’t address  the design critique but gives you a path forward ? 

I do agree that the semantics / default recursivity Of let bindings  can be inappropriate for non recursive code , but would any other non uniform semantics or optimization be safe?

On Fri, Aug 28, 2020 at 9:05 AM Spiwack, Arnaud <arnaud.spiwack@tweag.io> wrote:

Dear all,



I discovered the hard way, yesterday, that lazy let pattern
matching is allowed on unboxed tuples. And that it implicitly reboxes
the pattern.



Here is how the manual describes it, from the relevant section:





You can have an unboxed tuple in a pattern binding, thus



f x = let (# p,q #) = h x in ..body..



If the types of p and q are not unboxed, the resulting binding is lazy like any other Haskell pattern binding. The above example desugars like this:



f x = let t = case h x of { (# p,q #) -> (p,q) }

p = fst t

q = snd t

in ..body..



Indeed, the bindings can even be recursive.





Notice how h x is lazily bound, hence won’t necessarily be run when
body is forced. as opposed to if I had written, for instance,



let u = hx

in ..body..



My question is: are we happy with this? I did find this extremely
surprising. If I’m using unboxed tuples, it’s because I want to
guarantee to myself a strict, unboxed behaviour. But a very subtle
syntactic detail seems to break this expectation for me. My
expectation would be that I would need to explicitly rebox things
before they get lazy again.



I find that this behaviour invites trouble. But you may disagree. Let
me know!





_______________________________________________

ghc-devs mailing list

ghc-devs@haskell.org

http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

_______________________________________________
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs