
On Sun, Feb 03, 2013 at 10:34:04PM +0000, Ben Millwood wrote:
On Fri, Feb 01, 2013 at 05:10:42PM +0000, Ian Lynagh wrote:
The first is suggested by "A bang only really has an effect if it precedes a variable or wild-card pattern" on http://hackage.haskell.org/trac/haskell-prime/wiki/BangPatterns
We could therefore alter the lexical syntax to make strict things into lexems, for example reservedid -> ... | _ | !_ strictvarid -> ! varid etc. This would mean that "f !x" is 2 lexemes, and "f ! x" 3 lexemes, with the former defining the function 'f' and the latter defining the operator '!'.
This has 3 downsides:
* It would require also accepting the more radical proposal of making let strict, as it would no longer be possible to write let ![x,y] = undefined in ()
We really can't make let strict, in my view: its laziness is sort of fundamental. I don't see why the given example necessitates it though: just use case-of in that scenario.
Well, true, that's another option. It's rather unpleasant when you have multiple bindings, as when converted to 'case's, each 'case' requires you to indent deeper (or to use more braces).
The third is to parse '!' in patterns in the same way that '~' is parsed in patterns, except that (!) would be accepted as binding the operator '!'. This means that "f ! x" defines f.
This is roughly how it's done at present, right?
I think it's roughly what GHC does now, yes.
You missed the option of going the way of ~ and making ! an illegal name for an operator. Obvious drawbacks, probably not a good idea, but it would be the most consistent solution, so I wouldn't dismiss it immediately.
Yes, OK. That's basically option 3 as far as patterns are concerned, but also disallows ! as an operator.
(If we do come up with a way that doesn't involve making ! illegal, maybe we should consider allowing ~ as an operator as well!)
Right, if we went for option 3 then making ~ an operator in the same way as ! would be possible. I think we should be cautious about doing so, though, as it's a semi-one-way change, i.e. once it's an operator and people start using it it becomes a lot trickier to revert the decision.
Anyway, in light of my above comments, I think I like the first option the best (so bang patterns only apply to variables, let doesn't become strict).
So just to clarify what you're proposing, this wouldn't be valid: let ![x] = e in ... and I guess these wouldn't either?: let !x = e in ... let [!x] = e in ... let (x, ~(y, !z)) = e in ... but these would?: let f !x = e in ... case x of ~(y, !z) -> () i.e. you wouldn't be able to use ! in the 'pat' in the decl -> pat rhs production. You'd also no longer support: do ![x] <- e; ... and so again for consistency I guess these wouldn't work?: do !x <- e; ... do [!x] <- e; ... do (x, ~(y, !z)) <- e; ... i.e. you also wouldn't be able to use ! in the 'pat' in the stmt -> pat <- exp ; production. Thanks Ian