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

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

Thanks,
Ben

_______________________________________________
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime

Reply via email to