Re: Bang patterns

2013-02-08 Thread Doaitse Swierstra
I prefer them to be part of the context-free syntax, since this enables a 
future extension in which an arbitary expression can be placed between 
backticks. This would enable one to write things as:

 x `f i` y

and

expr1 `expr2` expr3 


is to be interpreted as (expr2) (expr1) (expr3),

 Doaitse




 


On Feb 8, 2013, at 13:27 , Simon Marlow 
 wrote:

> On 08/02/13 11:49, Ben Millwood wrote:
>> On Thu, Feb 07, 2013 at 12:24:48PM +, Simon Marlow wrote:
>>> FWIW, I really dislike whitespace-significant syntax.  f ! x should
>>> mean the same as f !x.  Look at the trouble we have with qualified
>>> operators: how many people have tried to write [Monday..] and been
>>> surprised that it doesn't work?
>> 
>> What about `elem`? I don't think anyone would argue that ` elem ` makes
>> sense.
> 
> Prelude> 1 ` elem ` [1..10]
> True
> Prelude> 1 ` {- comment -} elem ` [1..10]
> True
> 
> backticks are part of the context-free syntax, not the lexical syntax (as 
> they should be!).  I'm of the opinion that the lexical syntax should be as 
> simple, and as far as possible everything should be pushed into the 
> context-free syntax.
> 
> Cheers,
>   Simon
> 
> 
> ___
> Haskell-prime mailing list
> Haskell-prime@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-prime


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


Re: Bang patterns

2013-02-08 Thread Simon Marlow

On 08/02/13 11:49, Ben Millwood wrote:

On Thu, Feb 07, 2013 at 12:24:48PM +, Simon Marlow wrote:

FWIW, I really dislike whitespace-significant syntax.  f ! x should
mean the same as f !x.  Look at the trouble we have with qualified
operators: how many people have tried to write [Monday..] and been
surprised that it doesn't work?


What about `elem`? I don't think anyone would argue that ` elem ` makes
sense.


Prelude> 1 ` elem ` [1..10]
True
Prelude> 1 ` {- comment -} elem ` [1..10]
True

backticks are part of the context-free syntax, not the lexical syntax 
(as they should be!).  I'm of the opinion that the lexical syntax should 
be as simple, and as far as possible everything should be pushed into 
the context-free syntax.


Cheers,
Simon


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


Re: Bang patterns

2013-02-08 Thread Ben Millwood

On Thu, Feb 07, 2013 at 12:24:48PM +, Simon Marlow wrote:
FWIW, I really dislike whitespace-significant syntax.  f ! x should 
mean the same as f !x.  Look at the trouble we have with qualified 
operators: how many people have tried to write [Monday..] and been 
surprised that it doesn't work?


What about `elem`? I don't think anyone would argue that ` elem ` makes 
sense.


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


Re: Bang patterns

2013-02-07 Thread Atze Dijkstra

On  7 Feb, 2013, at 13:24 , Simon Marlow  wrote:

> On 04/02/13 23:42, Ian Lynagh wrote:
>> On Mon, Feb 04, 2013 at 10:37:44PM +, Simon Peyton-Jones wrote:
>>> 
>>> I don't have a strong opinion about whether
>>> f ! x y ! z = e
>>> should mean the same; ie whether the space is significant.   I think it's 
>>> probably more confusing if the space is significant (so its presence or 
>>> absence makes a difference).
>> 
>> I also don't feel strongly, although I lean the other way:
>> 
>> I don't think anyone writes "f ! x" when they mean "f with a strict
>> argument x", and I don't see any particular advantage in allowing it.
>> In fact, I think writing that is less clear than "f !x", so there is an
>> advantage in disallowing it.
>> 
>> It also means that existing code that defines a (!) operator in infix
>> style would continue to work, provided it puts whitespace around the !.
> 
> FWIW, I really dislike whitespace-significant syntax.  f ! x should mean the 
> same as f !x.  Look at the trouble we have with qualified operators: how many 
> people have tried to write [Monday..] and been surprised that it doesn't work?
> 
> So I don't mind at all if BangPatterns makes it harder to write a definition 
> of '!', because it's much more common to write bang patterns than it is to 
> define '!', and the workaround of writing (!) is not that onerous.
> 

I agree, I prefer the invariant that lexically whitespace does not matter. It 
is easier to understand, implement, and it is not such a big deal to have the 
choice of meaning (i.e. bang pattern or infix operator) depend on a LANGUAGE 
pragma, (re)defining ! is not that common anyway.

cheers,


   - Atze -

Atze Dijkstra, Department of Information and Computing Sciences. /|\
Utrecht University, PO Box 80089, 3508 TB Utrecht, Netherlands. / | \
Tel.: +31-30-2534118/1454 | WWW  : http://www.cs.uu.nl/~atze . /--|  \
Fax : +31-30-2513971  | Email: a...@uu.nl ... /   |___\




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


Re: Bang patterns

2013-02-07 Thread Simon Marlow

On 04/02/13 23:42, Ian Lynagh wrote:

On Mon, Feb 04, 2013 at 10:37:44PM +, Simon Peyton-Jones wrote:


I don't have a strong opinion about whether
f ! x y ! z = e
should mean the same; ie whether the space is significant.   I think it's 
probably more confusing if the space is significant (so its presence or absence 
makes a difference).


I also don't feel strongly, although I lean the other way:

I don't think anyone writes "f ! x" when they mean "f with a strict
argument x", and I don't see any particular advantage in allowing it.
In fact, I think writing that is less clear than "f !x", so there is an
advantage in disallowing it.

It also means that existing code that defines a (!) operator in infix
style would continue to work, provided it puts whitespace around the !.


FWIW, I really dislike whitespace-significant syntax.  f ! x should mean 
the same as f !x.  Look at the trouble we have with qualified operators: 
how many people have tried to write [Monday..] and been surprised that 
it doesn't work?


So I don't mind at all if BangPatterns makes it harder to write a 
definition of '!', because it's much more common to write bang patterns 
than it is to define '!', and the workaround of writing (!) is not that 
onerous.


Aside from preferring not to change the lexical syntax, I don't have a 
strong opinion. Your original third option, treating ! and ~ the same 
way, looks ok to me, but I also like the idea of only allowing bang 
patterns where they make sense (variables and pattern bindings).


Cheers,
Simon


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


Re: Bang patterns

2013-02-05 Thread Edward Kmett
On the topic of liberalizing operators that are currently only used in
patterns, another one that would be amazing to have as a valid term (or
type operator) is @ using similar () tricks. 1 character operator names are
in dreadful short supply and really help make nice DSLs.

-Edward

On Tue, Feb 5, 2013 at 8:42 AM, Ian Lynagh  wrote:

> On Mon, Feb 04, 2013 at 07:26:16PM -0500, Edward Kmett wrote:
> > If space sensitivity or () disambiguation is being used on !, could one
> of
> > these also be permitted on ~ to permit it as a valid infix term-level
> > operator?
>
> I don't think there's any reason ~ couldn't be an operator, defined with
> the
> (~) x y = ...
> syntax.
>
> Allowing it to be defined with infix syntax would be a little trickier.
>
>
> Hmm, I've just realised that if we decide to make !_ and !foo lexemes,
> then we'd also want !(+) to be a lexeme, which presumably means we'd
> want (+) to be a single lexeme too (and also `foo`, for consistency).
> But I don't think making that change would be problematic.
>
>
> Thanks
> Ian
>
>
> ___
> Haskell-prime mailing list
> Haskell-prime@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-prime
>
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Bang patterns

2013-02-05 Thread Ian Lynagh
On Mon, Feb 04, 2013 at 07:26:16PM -0500, Edward Kmett wrote:
> If space sensitivity or () disambiguation is being used on !, could one of
> these also be permitted on ~ to permit it as a valid infix term-level
> operator?

I don't think there's any reason ~ couldn't be an operator, defined with
the
(~) x y = ...
syntax.

Allowing it to be defined with infix syntax would be a little trickier.


Hmm, I've just realised that if we decide to make !_ and !foo lexemes,
then we'd also want !(+) to be a lexeme, which presumably means we'd
want (+) to be a single lexeme too (and also `foo`, for consistency).
But I don't think making that change would be problematic.


Thanks
Ian


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


Re: Bang patterns

2013-02-04 Thread Edward Kmett
If space sensitivity or () disambiguation is being used on !, could one of
these also be permitted on ~ to permit it as a valid infix term-level
operator?

That would be an amazingly valuable symbol to be able to reclaim for the
term level for equivalences, and for folks who come from other languages
where it is used like liftA2 (,) in parsing libraries, etc.

-Edward

On Mon, Feb 4, 2013 at 6:42 PM, Ian Lynagh  wrote:

> On Mon, Feb 04, 2013 at 10:37:44PM +, Simon Peyton-Jones wrote:
> >
> > I don't have a strong opinion about whether
> >   f ! x y ! z = e
> > should mean the same; ie whether the space is significant.   I think
> it's probably more confusing if the space is significant (so its presence
> or absence makes a difference).
>
> I also don't feel strongly, although I lean the other way:
>
> I don't think anyone writes "f ! x" when they mean "f with a strict
> argument x", and I don't see any particular advantage in allowing it.
> In fact, I think writing that is less clear than "f !x", so there is an
> advantage in disallowing it.
>
> It also means that existing code that defines a (!) operator in infix
> style would continue to work, provided it puts whitespace around the !.
>
>
> Thanks
> Ian
>
>
> ___
> Haskell-prime mailing list
> Haskell-prime@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-prime
>
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Bang patterns

2013-02-04 Thread Ben Millwood

On Mon, Feb 04, 2013 at 01:21:31PM -0800, Johan Tibell wrote:

On Sun, Feb 3, 2013 at 4:44 PM, Ben Millwood  wrote:

I have two proposals, I suppose:
- make bang patterns in let altogether invalid


I would prefer it to be valid. It's the syntactically most lightweight
option we have to force some thunks before using the resulting values
in a constructor that we have. Example

   let !x = ...
   !y = ...
   in C x y

The alternative would be

   let x = ...
   y = ...
   in x `seq` y `seq` C x y

which obscures the code much more.


I'd write (C $! x) $! y. We could devise a left-associative $! to avoid 
the use of parentheses here. But my objection was only ever a mild 
unease in any case, so I'm happy to dismiss it.


Ben

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


Re: Bang patterns

2013-02-04 Thread Ian Lynagh
On Mon, Feb 04, 2013 at 10:37:44PM +, Simon Peyton-Jones wrote:
> 
> I don't have a strong opinion about whether
>   f ! x y ! z = e
> should mean the same; ie whether the space is significant.   I think it's 
> probably more confusing if the space is significant (so its presence or 
> absence makes a difference).

I also don't feel strongly, although I lean the other way:

I don't think anyone writes "f ! x" when they mean "f with a strict
argument x", and I don't see any particular advantage in allowing it.
In fact, I think writing that is less clear than "f !x", so there is an
advantage in disallowing it.

It also means that existing code that defines a (!) operator in infix
style would continue to work, provided it puts whitespace around the !. 


Thanks
Ian


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


RE: Bang patterns

2013-02-04 Thread Simon Peyton-Jones
|  > I have two proposals, I suppose:
|  > - make bang patterns operate only on variables and wildcards
|  > - make bang patterns in let altogether invalid
|  
|  Looking at this again made me realise that, as well as !_ and !varid
|  lexemes, we could also alter the decl production so that we get
|  decl -> ...
|| pat rhs -- existing lazy binding production
|| '!' pat rhs -- new strict binding production
|  
|  That means that
|  let !(x, y) = e in ...
|  would still be valid, with the ! not actually being parsed as part of
|  the pattern, but would parse instead as a strict binding. 

Yes, I like this.  You could see the 
'!' pat rhs
production as cancelling the implied '~' that a let-binding usually gets (see 
the desugaring for lets in the report).

A bang really only makes sense
* At the top of a let, to cancel the implied '~'.  Like Johan I
   am very strongly in favour of using ! for this purpose.
* On a varid or '_', which otherwise match lazily
Hence Ian's proposal, which treats these two separately, makes sense.

For example, there's no point in the pattern (x, !(y,z)), because it behaves 
identically to (x, (y,z)).

We really do need to allow
f  !x  y !z = e
to mean f is strict in x and z.  There is an ambiguity here with a infix 
definition of (!), but it must be resolved in favour of the bang-pattern 
version.

I don't have a strong opinion about whether
f ! x y ! z = e
should mean the same; ie whether the space is significant.   I think it's 
probably more confusing if the space is significant (so its presence or absence 
makes a difference).

Simon



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


Re: Bang patterns

2013-02-04 Thread Johan Tibell
On Sun, Feb 3, 2013 at 4:44 PM, Ben Millwood  wrote:
> I have two proposals, I suppose:
> - make bang patterns in let altogether invalid

I would prefer it to be valid. It's the syntactically most lightweight
option we have to force some thunks before using the resulting values
in a constructor that we have. Example

let !x = ...
!y = ...
in C x y

The alternative would be

let x = ...
y = ...
in x `seq` y `seq` C x y

which obscures the code much more.

My 2 cents.

-- Johan

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


Re: Bang patterns

2013-02-03 Thread Ian Lynagh
On Mon, Feb 04, 2013 at 12:44:53AM +, Ben Millwood wrote:
> 
> I have two proposals, I suppose:
> - make bang patterns operate only on variables and wildcards
> - make bang patterns in let altogether invalid

Looking at this again made me realise that, as well as !_ and !varid
lexemes, we could also alter the decl production so that we get
decl -> ...
  | pat rhs -- existing lazy binding production
  | '!' pat rhs -- new strict binding production

That means that
let !(x, y) = e in ...
would still be valid, with the ! not actually being parsed as part of
the pattern, but would parse instead as a strict binding. It would be
a little ugly under the hood, as
let !x = e in ...
would parse as a lazy binding, although we'd want to treat it as a
strict binding anyway.


Thanks
Ian


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


Re: Bang patterns

2013-02-03 Thread Ben Millwood

On Sun, Feb 03, 2013 at 11:22:12PM +, Ian Lynagh wrote:

On Sun, Feb 03, 2013 at 10:34:04PM +, Ben Millwood wrote:

On Fri, Feb 01, 2013 at 05:10:42PM +, 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


Re: Bang patterns

2013-02-03 Thread Ian Lynagh
On Sun, Feb 03, 2013 at 10:34:04PM +, Ben Millwood wrote:
> On Fri, Feb 01, 2013 at 05:10:42PM +, 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


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


Re: Bang patterns

2013-02-03 Thread Ben Millwood

On Fri, Feb 01, 2013 at 05:10:42PM +, 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. In fact, I've kind of always been 
uncomfortable with bang patterns in let-statements. I feel like I should 
be able to omit an unused let-binding without affecting my program at 
all, and bang patterns in let make that no longer true.



* It would mean that "f !x" and "f !(x)" are different. Probably not a
 big issue in practice.


Yeah, I'm not upset about this. We'd be thinking of the ! as a decorator 
in the same way that, say, infix-backticks are: we don't expect `(foo)` 
to work.



* It may interact badly with other future extensions. For example,
   {-# LANGUAGE ViewPatterns #-}
   f !(view -> x) = ()
 should arguably be strict in x.
 (you might also argue that it should define the operator '!'.
 Currently, in ghc, it defines an 'f' that is lazy in x, which IMO is a
 bug).


Hmm. Not quite strict in x. I'd think the right way to make that strict 
in x is:


 f (view -> !x) = ()

What you want is possibly to evaluate the thing you pass to the view 
/before/ matching on the result. But I imagine that in most cases your 
view function will be strict so the difference will be immaterial.


I agree that GHC current behaviour looks like a bug.


The second is to parse '!' differently depending on whether or not it is
followed by a space. In the absence of a decision to require infix
operators to be surrounded by spaces, I think this is a bad idea: Tricky
to specify, and to understand.


Hmm. It's a shame because in real code operator definitions are almost 
invariably surrounded by spaces, even when the use of the operator 
wouldn't be. But I agree in general.



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? It's annoyingly 
inconsistent, but fairly low-impact.



So my proposal would be to go with option 3. What do you think? And did
I miss any better options?


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.


(If we do come up with a way that doesn't involve making ! illegal, 
maybe we should consider allowing ~ as an operator as well!)


There's another alternative entirely, that I haven't really thought 
about: introduce bang patterns on types instead of on variables. I 
realise this is less flexible, but! it covers many common cases, it 
avoids the infix confusion altogether, it echoes the existing usage for 
strict datatypes, and it makes the strictness of a function 
(potentially) part of its type signature, which would be handy in 
documentation. I realise this is a bit late in the game to be including 
this option, but if it doesn't get thought about now, it never will.


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


regards,
Ben

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


Bang patterns

2013-02-01 Thread Ian Lynagh

Hi all,

I would like to get a full specification of the bang patterns syntax,
partly so it can be proposed for H', and partly so we can resolve
tickets like http://hackage.haskell.org/trac/ghc/ticket/1087 correctly.


I think there are 3 possibilities:



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

* It would mean that "f !x" and "f !(x)" are different. Probably not a
  big issue in practice.

* It may interact badly with other future extensions. For example,
{-# LANGUAGE ViewPatterns #-}
f !(view -> x) = ()
  should arguably be strict in x.
  (you might also argue that it should define the operator '!'.
  Currently, in ghc, it defines an 'f' that is lazy in x, which IMO is a
  bug).



The second is to parse '!' differently depending on whether or not it is
followed by a space. In the absence of a decision to require infix
operators to be surrounded by spaces, I think this is a bad idea: Tricky
to specify, and to understand.



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.



So my proposal would be to go with option 3. What do you think? And did
I miss any better options?


Thanks
Ian


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


Re: Suggestion for bang patterns documentation

2009-02-27 Thread Christian Maeder
Brian Bloniarz wrote:
> I got confused by the GHC documentation recently, I was wondering how
> it could be improved. From:
> http://www.haskell.org/ghc/docs/latest/html/users_guide/bang-patterns.html

Seeing the rule
 pat ::= !pat

you'll probably want to avoid patterns like: "!!pat", "! ! pat", or "~ !
~ pat".

Even the current http://www.haskell.org/onlinelibrary/exps.html#sect3.17.1

  apat -> ~ apat

allows "~ ~x". (Note the space!) So maybe a separate non-terminal "bpat"
should be used with:

 bpat -> [~|!] apat

(and bpat used within pat). You may also want to exclude "v@ ~(...)" in
favor of "~v@(...)".

>> A bang only really has an effect if it precedes a variable or wild-card 
>> pattern:
>> f3 !(x,y) = [x,y]
>> f4 (x,y)  = [x,y]
>> Here, f3 and f4 are identical; putting a bang before a pattern that
>> forces evaluation anyway does nothing.

Maybe the duality (if it is one) should be added that an irrefutable
pattern above would make a difference but not within the let below.

> The first sentence is true, but only in settings where the pattern is being
> evaluated eagerly -- the bang in:
>> f3 a = let !(x,y) = a in [1,x,y]
>> f4 a = let (x,y) = a in [1,x,y]
> has an effect.

Cheers Christian

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


Re: Consistency of reserved operators and bang patterns

2007-09-27 Thread John Meacham
On Fri, Sep 07, 2007 at 09:24:51PM -0300, Isaac Dupree wrote:
> >Oh, and while we are at it, I think (:) should also be removed as a 
> >reservedop, there is no reason for it to be on that list.
> 
> Backwards compatibility requires that it be implicitly imported from 
> Prelude even in a module that does "import Prelude ( )" (although Hugs 
> is already broken in this regard).  And that makes it fairly useless as 
> a non-reserved symbol.  If not for that issue, I agree.

jhc is also broken in this regard. (:) is treated like any other
constructor.

John

-- 
John Meacham - ⑆repetae.net⑆john⑈
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Consistency of reserved operators and bang patterns

2007-09-08 Thread Neil Mitchell
Hi

Re ! as an operator: This caused a number of complexities in the
parsing of stuff, including shift-reduce conflicts. Someone would need
to look into this, and determine that the rules are completely
unambiguous.

> > Backwards compatibility requires that it be implicitly imported from
> > Prelude even in a module that does "import Prelude ( )" (although Hugs
> > is already broken in this regard).
>
> In particular, Haskell-98 bans
>
> import Prelude ( (:) )

Yhc does not meet this restriction either. Perhaps this is a change
that is breaking but minor enough to be permitted for H', since
everyone already does the reverse.

Thanks

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


Re: Consistency of reserved operators and bang patterns

2007-09-07 Thread Isaac Dupree

Isaac Dupree wrote:

Twan van Laarhoven wrote:
Oh, and while we are at it, I think (:) should also be removed as a 
reservedop, there is no reason for it to be on that list.


Backwards compatibility requires that it be implicitly imported from 
Prelude even in a module that does "import Prelude ( )" (although Hugs 
is already broken in this regard).


In particular, Haskell-98 bans

import Prelude ( (:) )

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


Re: Consistency of reserved operators and bang patterns

2007-09-07 Thread Isaac Dupree

Twan van Laarhoven wrote:
The bang pattern proposal [1] still allows (!) to be used as an 
operator. I think there should be no difference in this regard between ! 
and ~, since they are used in exactly the same location.


In my opinion the best thing would be to allow (~) and (@) as operators. 
With the same restriction on definition as (!), i.e. they must be 
defined in function style, not as an operator.


The change to the syntax would be to remove @ and ~ from the reserved 
operators list [2],

  reservedop -> .. | : | :: | = | \ | | | <- | -> | @ | ~ | =>
making it
  reservedop -> .. | : | :: | = | \ | | | <- | -> | =>


I agree - it confused me in the past that I couldn't define (@) or (~) 
operators.  Bang-pattern syntax being active will still change the 
meaning of


x ! y = z

of course.

Oh, and while we are at it, I think (:) should also be removed as a 
reservedop, there is no reason for it to be on that list.


Backwards compatibility requires that it be implicitly imported from 
Prelude even in a module that does "import Prelude ( )" (although Hugs 
is already broken in this regard).  And that makes it fairly useless as 
a non-reserved symbol.  If not for that issue, I agree.


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


Consistency of reserved operators and bang patterns

2007-09-07 Thread Twan van Laarhoven
The bang pattern proposal [1] still allows (!) to be used as an 
operator. I think there should be no difference in this regard between ! 
and ~, since they are used in exactly the same location.


In my opinion the best thing would be to allow (~) and (@) as operators. 
With the same restriction on definition as (!), i.e. they must be 
defined in function style, not as an operator.


The change to the syntax would be to remove @ and ~ from the reserved 
operators list [2],

  reservedop -> .. | : | :: | = | \ | | | <- | -> | @ | ~ | =>
making it
  reservedop -> .. | : | :: | = | \ | | | <- | -> | =>


Oh, and while we are at it, I think (:) should also be removed as a 
reservedop, there is no reason for it to be on that list.



Twan

[1] Bang Patterns, Haskell-prime wiki
http://hackage.haskell.org/trac/haskell-prime/wiki/BangPatterns

[2] Haskell 98 report, lexical structure, identifiers and operators
http://haskell.org/onlinereport/lexemes.html#sect2.4

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


Re: Bang patterns, ~ patterns, and lazy let

2006-02-08 Thread John Hughes

Simon Peyton-Jones wrote:


| What have you got in mind? ANY tupling of bindings may change the SCC
| structure, and hence the results of type inference--I'm taking that as
| read. But that still leaves the question of whether the dynamic
| semantics of the program is changed. Let's assume for the time being
| that all bindings carry a type signature--then the SCC structure is
| irrelevant, isn't it? Or am I missing something here? I'm under the
| impression that the *dynamic* semantics of
| 
| p1 = e1

| p2 = e2
| 
| *would* be the same as (p1,p2) = (e1,e2) under my strict matching

| proposal. I don't see how the SCC structure can affect that.

Well I put the example that you sent me on the Wiki, right at the
bottom.  Did I get it wrong?

 let { (y:ys) = xs; (z:zs) = ys } in body
means
 case xs of (y:ys) -> case ys of (z:zs) -> body

whereas
 let (y:ys, z:zs) = (xs,ys)  in body
means
 case (fix (\~(y:ys, z:zs). (xs,ys))) of (y:ys, z:zs) -> body

which isn't the same.

Simon
 


Oh yes, you're right of course.

In the denotational semantics I wrote last night, multiple bindings are 
combined using (+), which *is* the same as tupling them. But remember 
the thing I left unproven, because it was late at night?


E[[let defs1 in let defs2 in exp]]env = E[[let defs1; defs2 in exp]]env


It's not true, as this example shows. That'll teach me! In

let y:ys = xs; z:zs = ys in body

then the result is _|_, because matching the entire *group* against (xs, _|_) 
fails, but once the example is split into two nested lets then everything 
works. Yuck.


John

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


RE: Bang patterns, ~ patterns, and lazy let

2006-02-08 Thread Simon Peyton-Jones
| What have you got in mind? ANY tupling of bindings may change the SCC
| structure, and hence the results of type inference--I'm taking that as
| read. But that still leaves the question of whether the dynamic
| semantics of the program is changed. Let's assume for the time being
| that all bindings carry a type signature--then the SCC structure is
| irrelevant, isn't it? Or am I missing something here? I'm under the
| impression that the *dynamic* semantics of
| 
| p1 = e1
| p2 = e2
| 
| *would* be the same as (p1,p2) = (e1,e2) under my strict matching
| proposal. I don't see how the SCC structure can affect that.

Well I put the example that you sent me on the Wiki, right at the
bottom.  Did I get it wrong?

  let { (y:ys) = xs; (z:zs) = ys } in body
means
  case xs of (y:ys) -> case ys of (z:zs) -> body

whereas
  let (y:ys, z:zs) = (xs,ys)  in body
means
  case (fix (\~(y:ys, z:zs). (xs,ys))) of (y:ys, z:zs) -> body

which isn't the same.

Simon
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime


Re: Bang patterns, ~ patterns, and lazy let

2006-02-08 Thread John Hughes

Simon Peyton-Jones wrote:


I've updated the Wiki to add your strict proposal, but rather briefly.
If you want to add stuff, send it to me and I'll add it.

Meanwhile:

| And as a consequence, it is no longer possible to transform a pair of
| bindings into a binding of a pair. In Haskell 98,
| 
| p1 = e1

| p2 = e2
| 
| is always equivalent to
| 
| (~p1, ~p2) = (e1,e2)


In your strict proposal, I'm sure you hope that the above pair would be
equivalent to
(p1,p2) = (e1,e2)
which would be even nicer.

But sadly I don't think it is, because that'd change the strongly
connected component structure.  Somehow that smells wrong.

Simon
 

What have you got in mind? ANY tupling of bindings may change the SCC 
structure, and hence the results of type inference--I'm taking that as 
read. But that still leaves the question of whether the dynamic 
semantics of the program is changed. Let's assume for the time being 
that all bindings carry a type signature--then the SCC structure is 
irrelevant, isn't it? Or am I missing something here? I'm under the 
impression that the *dynamic* semantics of


   p1 = e1
   p2 = e2

*would* be the same as (p1,p2) = (e1,e2) under my strict matching 
proposal. I don't see how the SCC structure can affect that.


John

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


RE: Bang patterns, ~ patterns, and lazy let

2006-02-08 Thread Simon Peyton-Jones
I've updated the Wiki to add your strict proposal, but rather briefly.
If you want to add stuff, send it to me and I'll add it.

Meanwhile:

| And as a consequence, it is no longer possible to transform a pair of
| bindings into a binding of a pair. In Haskell 98,
| 
| p1 = e1
| p2 = e2
| 
| is always equivalent to
| 
| (~p1, ~p2) = (e1,e2)

In your strict proposal, I'm sure you hope that the above pair would be
equivalent to
(p1,p2) = (e1,e2)
which would be even nicer.

But sadly I don't think it is, because that'd change the strongly
connected component structure.  Somehow that smells wrong.

Simon
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime


Re: Bang patterns, ~ patterns, and lazy let

2006-02-08 Thread John Hughes

Simon Peyton-Jones wrote:


| The trouble with those parts is that NOWHERE do they discuss how to
| translate a let or where containing more than one binding. If they're
| not to be translated via tupling, then how are they to be translated?

Sorry I wasn't clear.  Given 
	let { p1 = e1; ... ; pn = en } in e0


(P1)  For each pattern pi that is of form !qi = ei, transform it to
[EMAIL PROTECTED] = ei
and replace e0 by (xi `seq` e0)

(P2)  Now no pattern has a ! at the top.  Now apply the existing rules
in
3.12 of the Haskell report.


So step (P1) above adds some seqs, and after that it's all just standard
Haskell 98.


My summary so far:
 


Good summary.


1) Bang patterns by themselves are quite decent, well-behaved patterns.

2) Rule (P1) is simple to describe.   But the ! in a pattern binding is
treated as part of the *binding* rather than part of the *pattern* which
is wart-y.
 

And as a consequence, it is no longer possible to transform a pair of 
bindings into a binding of a pair. In Haskell 98,


   p1 = e1
   p2 = e2

is always equivalent to

   (~p1, ~p2) = (e1,e2)

and you can make this change *locally*, without consideration of the 
body of the let in which the bindings appear. With ! bindings (let's use 
a different name from ! patterns, because they are not the same thing), 
there's no way to rewrite


   !p1 = e1
   !p2 = e2

as a single tuple binding, because there's nowhere you can put the ! 
that will have the same effect. Thus we lose a law from the algebra of 
bindings, which is part of the reason why this is warty.


John
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime


RE: Bang patterns, ~ patterns, and lazy let

2006-02-08 Thread Simon Peyton-Jones
| The trouble with those parts is that NOWHERE do they discuss how to
| translate a let or where containing more than one binding. If they're
| not to be translated via tupling, then how are they to be translated?

Sorry I wasn't clear.  Given 
let { p1 = e1; ... ; pn = en } in e0

(P1)  For each pattern pi that is of form !qi = ei, transform it to
[EMAIL PROTECTED] = ei
and replace e0 by (xi `seq` e0)

(P2)  Now no pattern has a ! at the top.  Now apply the existing rules
in
3.12 of the Haskell report.


So step (P1) above adds some seqs, and after that it's all just standard
Haskell 98.


My summary so far:

1) Bang patterns by themselves are quite decent, well-behaved patterns.

2) Rule (P1) is simple to describe.   But the ! in a pattern binding is
treated as part of the *binding* rather than part of the *pattern* which
is wart-y.

3) There is a good argument to be made that pattern bindings should be
strict by default.  That is
let (x,y) = e in b
would evaluate e strictly.  However that is *not* the same as saying
that 'let' is strict.  
let x = e in b
remains a lazy binding of x (because, as usual, a variable pattern
matches without evaluation).

4)  John argues that it would be bad to adopt bang patterns without also
adopting (3).  I don't agree.  But I'm still attracted by (3).
 

I will add some of this to the Wiki.  Please do not treat it as "my"
page --- any committee member can edit it.

Simon
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime


RE: Bang patterns, ~ patterns, and lazy let

2006-02-07 Thread John Hughes


 


From: Simon Peyton-Jones
To: John Hughes ; haskell-prime@haskell.org
Sent: Tuesday, February 07, 2006 11:37 PM
Subject: RE: Bang patterns, ~ patterns, and lazy let


Applying the rules on the wiki, the first step is to translate the first 
expression into a tuple binding, omitting the implicit ~:




Not so! I changed it a few days ago after talking to Ben, to a simpler 
form that works nicely for recursive bindings too. Darn I forgot to 
change the rules at the bottom.




Anyway, read the section “Let and where bindings”. Sorry about the rules 
at the end.




Simon

The trouble with those parts is that NOWHERE do they discuss how to 
translate a let or where containing more than one binding. If they're 
not to be translated via tupling, then how are they to be translated? 
The only relevant thing I could find was in the "modifications to the 
report" section at the bottom, which just tells you to omit implicit ~ 
when applying the tuplling rules in the report.




So I don't understand how the semantics of multiple bindings is supposed 
to be defined (and I admit my proposal isn't so nice either). But more 
and more complex translations make me very nervous!




I have a feeling there could be a nice direct semantics, though, 
including both ! and ~ in a natural way. Let's see now.




Let environments be (unlifted) functions from identifiers to values, 
mapping unbound identifiers to _|_ for simplicity. The semantics of 
patterns is given by




P[[pat]] :: Value -> Maybe Env



The result is Just env if matching succeeds, Nothing if matching fails, 
and _|_ if matching loops.




Two important clauses:



P[[! pat]] v = _|_ if v=_|_

P[[pat]]v otherwise



P[[~ pat]] v = Just _|_ if P[[pat]]v <= Nothing

P[[pat]]v otherwise



In definitions, pattern matching failure is the same as looping, so we 
define




P'[[pat]]v = _|_ if P[[pat]]v = Nothing

P[[pat]]v otherwise



We do need to distinguish, though, between _|_ (match failure or 
looping), and Just _|_ (success, binding all variables to _|_).




The semantics of a definition in an environment is



D[[pat = exp]]env = P'[[pat]] (E[[exp]]env) (*)



where E is the semantics of expressions. Note that this takes care of 
both ! and ~ on the top level of a pattern.




Multiple definitions are interpreted by



D[[d1 ; d2]]env = D[[d1]]env (+) D[[d2]]env



where (+) is defined by



_|_ (+) _ = _|_

Just env (+) _|_ = _|_

Just env (+) Just env' = Just (env |_| env')



Note that (+) is associative and commutative.



Let's introduce an explicit marker for recursive declarations:



D[[rec defs]]env = fix menv'. D[[defs]](env |_| fromJust menv')



Notice:



This ignores the possibility of local variables shadowing variables from 
outer scopes.




*Within defs* it makes no difference whether menv' is _|_ (matching 
fails or loops), or Just _|_ (succeeds with variables bound to _|_)




If defs are not actually recursive, then D[[rec defs]]env = D[[defs]]env.



Now let expressions are defined by



E[[let defs in exp]]env = E[[exp]](env |_| D[[rec defs]]env)



(this also ignores the possibility of local definitions shadowing 
variables from an outer scope).




Too late at night to do it now, but I have the feeling that it should 
not be hard now to prove that




E[[let defs1 in let defs2 in exp]]env = E[[let defs1; defs2 in exp]]env



under suitable assumptions on free variable occurrences. That implies, 
together with commutativity and associativity of (+), that the division 
of declaration groups into strongly connected components does not affect 
semantics.




I like this way of giving semantics--at least I know what it means! But 
it does demand, really, that matching in declarations is strict by 
default. Otherwise I suppose, if one doesn't care about 
compositionality, one could replace definition (*) above by




D[[!pat = exp]]env = P'[[pat]](E[[exp]]env)

D[[pat = exp]]env = P'[[~pat]](E[[exp]]env), otherwise



But this really sucks big-time, doesn't it?



John

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


RE: Bang patterns, ~ patterns, and lazy let

2006-02-07 Thread Simon Peyton-Jones










Applying the rules on the wiki, the first step is to
translate the first _expression_ into a tuple binding, omitting the implicit ~:

 

Not so!  I changed it a few days ago
after talking to Ben, to a simpler form that works nicely for recursive
bindings too.  Darn – I forgot to change the rules at the bottom.

 

Anyway, read the section “Let and
where bindings”. Sorry about the rules at the end.

 

Simon








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


Re: Bang patterns, ~ patterns, and lazy let

2006-02-07 Thread John Hughes






  
From: Ben Rudiak-Gould <[EMAIL PROTECTED]>
Subject: Re: Bang patterns, ~ patterns, and lazy let


  It's also not that case that !x has the same 
meaning in both proposals, e.g.

 let { !x = y ; !y = const 'a' x } in x

means 'a' in the current proposal but _|_ in yours.
  

Aargh, you're right, it does mean _|_ in mine! That's not very nice.

But wait, I'm not sure about
 let { !x = const undefined y ; !y = const 'a' x } in y
  
desugars in the current proposal to
  
let { x = const undefined y ; y = const 'a' x } in x `seq` y `seq` y
  
which is _|_, but absent implicit ~,
  
let { x = const undefined y ; y = const 'a' x } in y
  
had better (and does) mean 'a'. 
Applying the rules on the wiki, the first step is to translate the
first _expression_ into a tuple binding, omitting the implicit ~:

    let (x,y) = (const undefined y, const 'a' x) in y

This desugars to

    let (x,y) = fix (\ ~(x,y)->(const undefined y, const 'a' x)) in y

which evaluates to 'a'. In other words, despite the ! on x, the current
proposal is not strict in x.

Maybe the intention was that !s on the lhs of let bindings should be
transferred to the corresponding patterns when a tuple pattern is
introduced? Let's try it: then the example desugars by pattern tupling
to

    let (!x, !y) = (const undefined y, const 'a' x) in y

Now we can introduce fix:

    let (!x, !y) = fix (\ ~(!x, !y) -> (const undefined y, const 'a'
x)) in y

and finally case:

    case fix (\~(!x,!y) -> (const undefined y, const 'a' x)) of
~(!x, !y) -> y

and this is consistent with what you said above.

But if I return to your first example, and do the same thing, I get

    let !x = y; !y = const 'a' x in x

desugars by tupling to

    let (!x, !y) = (y, const 'a' x) in x

which desugars by fix and case introduction to

    case fix (\ ~(!x, !y) -> (y, const 'a' x)) of ~(!x, !y) -> x

The first approximation to the fixed point is _|_, so the second is
(_|_, 'a'). Now, when ~(!x,!y) is matched against (_|_,'a') then *both*
variables are bound to _|_ --- the effect of the ~ is just to delay
matching (!x,!y) until one of the variables is used, but as soon as y,
say, *is* used, then the match is performed and, of course, it loops.
Thus (_|_, 'a') is the fixed point. For the same reason, x and y are
both bound to _|_ in the body of the case, and so the entire _expression_
evaluates to _|_, not 'a' as you claimed.

Bottom line: I can't find a way to interpret the translation rules in
the Haskell report, modified as the Wiki page suggests, to produce the
results you expect in both cases.

But maybe the fault is in the translation rules in the Haskell report.
It was always rather tricky to explain a group of recursive bindings in
Haskell in terms of a single tuple binding, because Haskell tuples are
lifted. I see that you have a more direct understanding of what ! is
supposed to mean. Is it possible, I wonder, to give a direct
denotational semantics to a declaration group--say mapping environments
to environments--in which there is only one case for ! (its natural
semantics in patterns)? Such a semantics should have the property that

    let x1 = e1; x2 = e2 in e0   ===   let x1 = e1 in let x2 = e2 in e0

provided x1 does not occur in e2. Finding a simple and compositional
denotational semantics with these properties, and proving the law
above, would be a good way to show that ! patterns do NOT introduce
semantic warts---and would probably also suggest that the
semantics-by-translation used in the report is fundamentally flawed. We
did construct denotational semantics of fragments of Haskell as part of
the original design, and it had quite an impact on the result--I
recommend it as a way of debugging ideas!

John


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


Re: Bang patterns, ~ patterns, and lazy let

2006-02-07 Thread Ben Rudiak-Gould

John Hughes wrote:

* ! on the left hand side of a let or where *has a different meaning to !
in a pattern* -- it means that the ~ that would have been implicitly 
inserted by the previous rule, is not inserted after all!


I wish it were that simple, but I don't think it is.

let { !x = const undefined y ; !y = const 'a' x } in y

desugars in the current proposal to

let { x = const undefined y ; y = const 'a' x } in x `seq` y `seq` y

which is _|_, but absent implicit ~,

let { x = const undefined y ; y = const 'a' x } in y

had better (and does) mean 'a'. It's also not that case that !x has the same 
meaning in both proposals, e.g.


let { !x = y ; !y = const 'a' x } in x

means 'a' in the current proposal but _|_ in yours.

My experience is that "top-level" strictness information has a very 
different nature from "nested" strictness information, and it's not 
generally possible to find a single interpretation that covers both. The 
reason is that strictness is a relationship between a value and its 
continuation (i.e. context). Nested strictness annotations connect data to a 
datatype context; top-level strictness annotations in this case connect data 
to either a case context or a let context. Each of the three situations has 
to be considered separately.



This is not the same as banging the pattern with the implicit ~, because
as I remarked above, !~p is not the same as p.


Actually if ! patterns were handled consistently in let they would come out 
as ~!p = ~p, so the ! would have no effect. The current proposal effectively 
borrows the ! notation, which would otherwise be useless, for a different 
purpose in this case.


-- Ben

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


Re: Bang patterns, ~ patterns, and lazy let

2006-02-07 Thread John Hughes


   From: Ross Paterson <[EMAIL PROTECTED]>
   John Hughes wrote:

I would urge that either we stick with the present design, or, if bang 
patterns are added (which a lot speaks for), that the language be 
simplified at the same time so that patterns are matched in the same way 
everywhere, and BOTH warts above are excised. Some existing code would 
break, but in return the language would become simpler and more expressive.
   


   Would top-level bindings of constructor patterns and !x be evaluated
   when the module was loaded (or at compile time)?


Yes. Nothing else makes sense, does it? If that's problematic (although 
I can't see why it would be), just forbid strict patterns at the top 
level of modules.


Load time rather than compile-time, I think--otherwise the compiled code 
for a module could depend on the *code* of modules it imports, not just 
on their interfaces, which would be harmful for separate compilation.


John

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


Re: Bang patterns, ~ patterns, and lazy let

2006-02-07 Thread Ross Paterson
On Tue, Feb 07, 2006 at 09:02:36AM +0100, John Hughes wrote:
> I would urge that either we stick with the present design, or, if bang 
> patterns are added (which a lot speaks for), that the language be 
> simplified at the same time so that patterns are matched in the same way 
> everywhere, and BOTH warts above are excised. Some existing code would 
> break, but in return the language would become simpler and more expressive.

Would top-level bindings of constructor patterns and !x be evaluated when
the module was loaded (or at compile time)?

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


Bang patterns, ~ patterns, and lazy let

2006-02-07 Thread John Hughes

I just looked at the bang pattern proposal in more detail. To summarise:

* Pattern-matching is presently strict against constructors, lazy 
against variables.
* ~p matches p lazily; matching always succeeds, binding the variables 
in p to _|_ if matching p fails.
* !p matches p strictly; matching always loops if the value matched is 
_|_, even if p is a variable or ~ pattern.


Note that !~p is not the same as p (matching it can never fail, p itself 
is not matched strictly), but ~!p is the same as ~p.


So far, so good--everything has a clean semantics and is easy to 
understand.  Now for the warts:


* Patterns on the left hand side of a let or where are implicitly 
preceded by ~, making matching in these contexts lazy by default.
* ! on the left hand side of a let or where *has a different meaning to 
! in a pattern* -- it means that the ~ that would have been implicitly 
inserted by the previous rule, is not inserted after all! This is not 
the same as banging the pattern with the implicit ~, because as I 
remarked above, !~p is not the same as p.


This really, really smacks of committee design, doesn't it? Come on, 
it's a dog's breakfast! I've made clear before that I consider the FIRST 
rule above (that matching in let and where has an implicit ~) to be a 
wart already, but giving ! a second meaning to control whether or not 
the first wart is really applied is growing warts on warts!


The one good thing to be said for this design is that it doesn't break 
existing code. But really--the design is unreasonably complex, and would 
just store up trouble for the future. Imagine trying to make a further 
extension to pattern matching next time Haskell is revised, without 
breaking code that relies on the warts on warts above!


I would urge that either we stick with the present design, or, if bang 
patterns are added (which a lot speaks for), that the language be 
simplified at the same time so that patterns are matched in the same way 
everywhere, and BOTH warts above are excised. Some existing code would 
break, but in return the language would become simpler and more expressive.


John
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime


Re: Bang patterns

2006-02-06 Thread Ben Rudiak-Gould
Pursuant to a recent conversation with Simon, my previous post to this 
thread is now obsolete. So please ignore it, and see the updated wiki page 
instead.


-- Ben

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


Re: Bang patterns

2006-02-06 Thread Ben Rudiak-Gould

Simon Peyton-Jones wrote:

http://haskell.galois.com/cgi-bin/haskell-prime/trac.cgi/wiki/BangPatterns


You say that

let !(x, Just !y) =  in 

can't be desugared to

let
  t = 
  x = case t of (x, Just !y) -> x
  y = case t of (x, Just !y) -> y
in
t `seq` 

and I agree. But that's not the desugaring I'd expect; I'd expect this:

let t1@(x, Just [EMAIL PROTECTED]) =  in t1 `seq` t2 `seq` 

which does have the appropriate semantics, I think.

You can also desugar let ![x,y] = e in b to let [EMAIL PROTECTED],y] = e in t1 `seq` b 
instead of case e of { [x,y] -> b }, which would solve the polymorphism problem.


The other thing that isn't obvious to me is what should happen when ! is 
nested inside ~. Naively


case e of { (x,~(y,!z)) -> b }

should be equivalent to

case e of { (x,t1) -> let (y,!z) = t1 in b }

which should be equivalent to

case e of { (x,t1) -> let (y,[EMAIL PROTECTED]) = t1 in t2 `seq` b }

But this is the same as

case e of { (x,(y,!z)) -> b }

In other words, the ~ has no effect, which is not what I expect. I think 
there's an incompatibility between the interpretation of ! in let and case 
expressions. In let expressions it needs to be able to escape from the 
implicit ~, while in case expressions it should stay inside. One possible 
solution would be to make top-level ~ significant in let expressions, but 
that feels a bit strange too.


Another minor point: allowing

  module Foo where
!x = ...

would mean that adding an import statement to a terminating program could 
change it into a nonterminating one.


-- Ben

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


Bang patterns

2006-02-06 Thread Simon Peyton-Jones
Earlier on the Haskell' list, I proposed bang patterns as a way to make
it more convenient for Haskell programmers to make their programs
stricter.  E.g.
f (!x, y) = 

I've documented the proposal here

http://haskell.galois.com/cgi-bin/haskell-prime/trac.cgi/wiki/BangPatter
ns

I've implemented it in GHC, so you can try it out.  Use
-fbang-patterns
to enable bang patterns.   If you use -fglasgow-exts you get
-fbang-patterns as well.  If you don't want that, use -fglasgow-exts
-fno-bang-patterns.

I'd be interested to hear your experiences.  (Committee members: do add
notes to the Wiki page giving pros and cons.)

Simon 
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime