Bang patterns

Ben Millwood haskell at
Mon Feb 4 01:44:53 CET 2013

On Sun, Feb 03, 2013 at 11:22:12PM +0000, Ian Lynagh wrote:
>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
>> >
>> >
>> >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).

Yes, or you could use a tuple, or you could use seq directly, but I 
recognise those options as having their own drawbacks.

(Observation: if bang patterns are made primitive, seq can be implemented 
as an ordinary function in terms of them.)

>> (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.

Yeah, I wouldn't be overeager to do it, just worth remembering that that 
option becomes open.

>> 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 have two proposals, I suppose:
- make bang patterns operate only on variables and wildcards
- make bang patterns in let altogether invalid

(with an optional third, "make bang patterns something else entirely")

with the justification for the first being that it is the most common 
case and interferes less with the infix operator !, and the 
justification for the second being the somewhat weedier general notion 
that I think unused let bindings should be discardable, and that I think 
bang-lets confuse the distinction between case and let (but then, 
arguably ~ already does that).

So, my proposal is the following definitely ARE allowed:

>    let f !x = e in ...
>    case x of ~(y, !z) -> ()

The following definitely AREN'T:

>    let ![x] = e in ...
>    do ![x]          <- e; ...

but the following are allowed by the first proposal but disallowed by 
the second:

>    let !x = e in ...
>    let [!x] = e in ...
>    let (x, ~(y, !z)) = e in ...
>    do !x            <- e; ...
>    do [!x]          <- e; ...
>    do (x, ~(y, !z)) <- e; ...

I'm not committed to this plan. I can see especially why the second 
pattern on my forbidden list might be useful. But I don't like making 
operator-! special.

(I still think types might be the right place to put this information).


More information about the Haskell-prime mailing list