-XStrict: Why some binders are not made strict?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

-XStrict: Why some binders are not made strict?

Ömer Sinan Ağacan
Let's say I have this code:

    zip :: [a] -> [b] -> [(a, b)]
    zip [] [] = []
    zip (x : xs) (y : ys) = (x, y) : zip xs ys

With -XStrict 'x', 'xs', 'y' and 'ys' don't become strict. I'm wondering about
the motivation behind this, I found this interesting. I always thought -XStrict
gives me this guarantee: If I'm using an already-defined variable(bound by a
let or pattern matching) in an expression, I can be sure that the variable
won't be bottom in that expression, because it would be `seq`d before the
expression is evaluated.

So if I have

    case ... of
        D x y -> <body>

or

    let x = ...
        y = ...
     in <body>

In both cases I was thinking that in <body> 'x' and 'y' can't be bottom(with
-XStrict). This would make -XStrict programs evaluate like they would in a
call-by-value language(even though in the RTS level thunks will be built).
Variables can't range over computations; all binders evaluated strictly etc.

Can anyone tell me about the motivation behind this decision?

I think the wiki page actually conflicts with itself. It says "...
bindings to be
strict by default" but then in "case expressions" sections says

    case x of (a,b) -> rhs

    is interpreted as

    case x of !(a,b) -> rhs

Here bindings 'a' and 'b' are not made strict. I'd expect something like:

    case x of (!a,!b) -> rhs

(Which seems to be invalid Haskell, but same effect could be achieved with `seq
a (seq b rhs)`)

Thanks..

(I also realized that the wiki page doesn't mention bindings in do syntax, is
it because this case is implied by "function definitions"? That is, bangs are
added after do syntax is desugared and so they become strict?)
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Brandon Allbery
On Mon, Dec 7, 2015 at 8:40 PM, Ömer Sinan Ağacan <[hidden email]> wrote:
With -XStrict 'x', 'xs', 'y' and 'ys' don't become strict. I'm wondering about
the motivation behind this, I found this interesting. I always thought -XStrict
gives me this guarantee: If I'm using an already-defined variable(bound by a
let or pattern matching) in an expression, I can be sure that the variable
won't be bottom in that expression, because it would be `seq`d before the
expression is evaluated.

Aren't those already guaranteed to be strict because of pattern matching? Try it again with irrefutable patterns.

--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Ömer Sinan Ağacan
> Aren't those already guaranteed to be strict because of pattern matching? Try
> it again with irrefutable patterns.

But pattern matching only forces the evaluation up to the pattern that is
matched. We need another pattern matching(or seq etc.) on x, y, xs and ys here.
If you look at the generated Core you'll see it more clearly I think(you'll see
that no pattern matching on x y xs and ys are done in Core).

2015-12-07 20:43 GMT-05:00 Brandon Allbery <[hidden email]>:

> On Mon, Dec 7, 2015 at 8:40 PM, Ömer Sinan Ağacan <[hidden email]>
> wrote:
>>
>> With -XStrict 'x', 'xs', 'y' and 'ys' don't become strict. I'm wondering
>> about
>> the motivation behind this, I found this interesting. I always thought
>> -XStrict
>> gives me this guarantee: If I'm using an already-defined variable(bound by
>> a
>> let or pattern matching) in an expression, I can be sure that the variable
>> won't be bottom in that expression, because it would be `seq`d before the
>> expression is evaluated.
>
>
> Aren't those already guaranteed to be strict because of pattern matching?
> Try it again with irrefutable patterns.
>
> --
> brandon s allbery kf8nh                               sine nomine associates
> [hidden email]                                  [hidden email]
> unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

RE: -XStrict: Why some binders are not made strict?

Simon Peyton Jones
In reply to this post by Ömer Sinan Ağacan
Adam, Johan,

Looking at the user manual
http://downloads.haskell.org/~ghc/master/users-guide/glasgow_exts.html#strict-haskell,
and indeed the wiki page
https://ghc.haskell.org/trac/ghc/wiki/StrictPragma
it's not really clear whether the sub-components of a pattern are strict.  That is, is the second equation of zip strict in x, and xs?   (Supposing for now that the list data structure is lazy).  The manual doesn't say one way or the other.

What's the answer?  And could the user manual please say?

Thanks

Simon

| -----Original Message-----
| From: ghc-devs [mailto:[hidden email]] On Behalf Of Ömer
| Sinan Agacan
| Sent: 08 December 2015 01:41
| To: ghc-devs <[hidden email]>
| Subject: -XStrict: Why some binders are not made strict?
|
| Let's say I have this code:
|
|     zip :: [a] -> [b] -> [(a, b)]
|     zip [] [] = []
|     zip (x : xs) (y : ys) = (x, y) : zip xs ys
|
| With -XStrict 'x', 'xs', 'y' and 'ys' don't become strict. I'm wondering
| about
| the motivation behind this, I found this interesting. I always thought -
| XStrict
| gives me this guarantee: If I'm using an already-defined variable(bound by
| a
| let or pattern matching) in an expression, I can be sure that the variable
| won't be bottom in that expression, because it would be `seq`d before the
| expression is evaluated.
|
| So if I have
|
|     case ... of
|         D x y -> <body>
|
| or
|
|     let x = ...
|         y = ...
|      in <body>
|
| In both cases I was thinking that in <body> 'x' and 'y' can't be
| bottom(with
| -XStrict). This would make -XStrict programs evaluate like they would in a
| call-by-value language(even though in the RTS level thunks will be built).
| Variables can't range over computations; all binders evaluated strictly
| etc.
|
| Can anyone tell me about the motivation behind this decision?
|
| I think the wiki page actually conflicts with itself. It says "...
| bindings to be
| strict by default" but then in "case expressions" sections says
|
|     case x of (a,b) -> rhs
|
|     is interpreted as
|
|     case x of !(a,b) -> rhs
|
| Here bindings 'a' and 'b' are not made strict. I'd expect something like:
|
|     case x of (!a,!b) -> rhs
|
| (Which seems to be invalid Haskell, but same effect could be achieved with
| `seq
| a (seq b rhs)`)
|
| Thanks..
|
| (I also realized that the wiki page doesn't mention bindings in do syntax,
| is
| it because this case is implied by "function definitions"? That is, bangs
| are
| added after do syntax is desugared and so they become strict?)
| _______________________________________________
| ghc-devs mailing list
| [hidden email]
| https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.haske
| ll.org%2fcgi-bin%2fmailman%2flistinfo%2fghc-
| devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7cbc68c0830f574466efd
| 308d2ff70aba9%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=c2VBbt%2f%2fR2c
| yFecGEuQotO%2bV71VSbpmWnZJyV9d8KRk%3d
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Johan Tibell-2
I'm snowed under but I promise I will try to reply soon! To think about in the mean time: what do existing strict languages with pattern matching do?

On Tue, Dec 8, 2015 at 3:42 PM, Simon Peyton Jones <[hidden email]> wrote:
Adam, Johan,

Looking at the user manual
http://downloads.haskell.org/~ghc/master/users-guide/glasgow_exts.html#strict-haskell,
and indeed the wiki page
https://ghc.haskell.org/trac/ghc/wiki/StrictPragma
it's not really clear whether the sub-components of a pattern are strict.  That is, is the second equation of zip strict in x, and xs?   (Supposing for now that the list data structure is lazy).  The manual doesn't say one way or the other.

What's the answer?  And could the user manual please say?

Thanks

Simon

| -----Original Message-----
| From: ghc-devs [mailto:[hidden email]] On Behalf Of Ömer
| Sinan Agacan
| Sent: 08 December 2015 01:41
| To: ghc-devs <[hidden email]>
| Subject: -XStrict: Why some binders are not made strict?
|
| Let's say I have this code:
|
|     zip :: [a] -> [b] -> [(a, b)]
|     zip [] [] = []
|     zip (x : xs) (y : ys) = (x, y) : zip xs ys
|
| With -XStrict 'x', 'xs', 'y' and 'ys' don't become strict. I'm wondering
| about
| the motivation behind this, I found this interesting. I always thought -
| XStrict
| gives me this guarantee: If I'm using an already-defined variable(bound by
| a
| let or pattern matching) in an expression, I can be sure that the variable
| won't be bottom in that expression, because it would be `seq`d before the
| expression is evaluated.
|
| So if I have
|
|     case ... of
|         D x y -> <body>
|
| or
|
|     let x = ...
|         y = ...
|      in <body>
|
| In both cases I was thinking that in <body> 'x' and 'y' can't be
| bottom(with
| -XStrict). This would make -XStrict programs evaluate like they would in a
| call-by-value language(even though in the RTS level thunks will be built).
| Variables can't range over computations; all binders evaluated strictly
| etc.
|
| Can anyone tell me about the motivation behind this decision?
|
| I think the wiki page actually conflicts with itself. It says "...
| bindings to be
| strict by default" but then in "case expressions" sections says
|
|     case x of (a,b) -> rhs
|
|     is interpreted as
|
|     case x of !(a,b) -> rhs
|
| Here bindings 'a' and 'b' are not made strict. I'd expect something like:
|
|     case x of (!a,!b) -> rhs
|
| (Which seems to be invalid Haskell, but same effect could be achieved with
| `seq
| a (seq b rhs)`)
|
| Thanks..
|
| (I also realized that the wiki page doesn't mention bindings in do syntax,
| is
| it because this case is implied by "function definitions"? That is, bangs
| are
| added after do syntax is desugared and so they become strict?)
| _______________________________________________
| ghc-devs mailing list
| [hidden email]
| https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.haske
| ll.org%2fcgi-bin%2fmailman%2flistinfo%2fghc-
| devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7cbc68c0830f574466efd
| 308d2ff70aba9%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=c2VBbt%2f%2fR2c
| yFecGEuQotO%2bV71VSbpmWnZJyV9d8KRk%3d


_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Adam Sandberg Eriksson
When implementing I took this:
 
> Notice that we do not put bangs on nested patterns. For example
>   let (p,q) = if flob then (undefined, undefined) else (True, False)
>    in ...
> will behave like
>   let !(p,q) = if flob then (undefined, undefined) else (True, False)
>   in ...
 
(from the spec) and applied it to all bindings, but I don't know if this is the best implementation.
 
Cheers,
Adam 
 
 
On Thu, 10 Dec 2015, at 03:34 PM, Johan Tibell wrote:
I'm snowed under but I promise I will try to reply soon! To think about in the mean time: what do existing strict languages with pattern matching do?
 
On Tue, Dec 8, 2015 at 3:42 PM, Simon Peyton Jones <[hidden email]> wrote:
Adam, Johan,
 
Looking at the user manual
and indeed the wiki page
it's not really clear whether the sub-components of a pattern are strict.  That is, is the second equation of zip strict in x, and xs?   (Supposing for now that the list data structure is lazy).  The manual doesn't say one way or the other.
 
What's the answer?  And could the user manual please say?
 
Thanks
 
Simon
 
| -----Original Message-----
| From: ghc-devs [mailto:[hidden email]] On Behalf Of Ömer
| Sinan Agacan
| Sent: 08 December 2015 01:41
| To: ghc-devs <[hidden email]>
| Subject: -XStrict: Why some binders are not made strict?
|
| Let's say I have this code:
|
|     zip :: [a] -> [b] -> [(a, b)]
|     zip [] [] = []
|     zip (x : xs) (y : ys) = (x, y) : zip xs ys
|
| With -XStrict 'x', 'xs', 'y' and 'ys' don't become strict. I'm wondering
| about
| the motivation behind this, I found this interesting. I always thought -
| XStrict
| gives me this guarantee: If I'm using an already-defined variable(bound by
| a
| let or pattern matching) in an expression, I can be sure that the variable
| won't be bottom in that expression, because it would be `seq`d before the
| expression is evaluated.
|
| So if I have
|
|     case ... of
|         D x y -> <body>
|
| or
|
|     let x = ...
|         y = ...
|      in <body>
|
| In both cases I was thinking that in <body> 'x' and 'y' can't be
| bottom(with
| -XStrict). This would make -XStrict programs evaluate like they would in a
| call-by-value language(even though in the RTS level thunks will be built).
| Variables can't range over computations; all binders evaluated strictly
| etc.
|
| Can anyone tell me about the motivation behind this decision?
|
| I think the wiki page actually conflicts with itself. It says "...
| bindings to be
| strict by default" but then in "case expressions" sections says
|
|     case x of (a,b) -> rhs
|
|     is interpreted as
|
|     case x of !(a,b) -> rhs
|
| Here bindings 'a' and 'b' are not made strict. I'd expect something like:
|
|     case x of (!a,!b) -> rhs
|
| (Which seems to be invalid Haskell, but same effect could be achieved with
| `seq
| a (seq b rhs)`)
|
| Thanks..
|
| (I also realized that the wiki page doesn't mention bindings in do syntax,
| is
| it because this case is implied by "function definitions"? That is, bangs
| are
| added after do syntax is desugared and so they become strict?)
| _______________________________________________
| ghc-devs mailing list
| ll.org%2fcgi-bin%2fmailman%2flistinfo%2fghc-
| devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7cbc68c0830f574466efd
| 308d2ff70aba9%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=c2VBbt%2f%2fR2c
| yFecGEuQotO%2bV71VSbpmWnZJyV9d8KRk%3d
 

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Roman Cheplyaka-2
In reply to this post by Johan Tibell-2
On 12/10/2015 04:34 PM, Johan Tibell wrote:
> I'm snowed under but I promise I will try to reply soon! To think about
> in the mean time: what do existing strict languages with pattern
> matching do?

Well, strict languages do not have lazy data to force to begin with, do they?

Personally, I find the simple intuition of "all patterns are strict by default" rather appealing.

E.g. I wouldn't expect the expressions

  let (v1,v2) = a in f v2

and

  let (v1,v2) = a; v3 = v2 in f v3

to have different semantics.

If we decide to adopt this semantics, we need to address the meaning of the pattern

  ~(v1, v2)

under -XStrict. Intuitively, ~ should propagate to the subpatterns. An alternative is to disallow this pattern under -XStrict and require writing all ~s explicitly, which may get tedious:

  ~(~v1, ~v2)
  ~(~v1, ~(~v2, ~v3))
  etc.

We also need to ensure the consistency between this extension and the unlifted data types proposal [1], given their similarity. Interestingly, I don't see constructor patterns explained there either.

[1]: https://ghc.haskell.org/trac/ghc/wiki/UnliftedDataTypes#Dynamicsemanticsofunliftedtypes



_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Johan Tibell-2
I believe Scala has optional lazy values, but you could also consider in strict languages if you do manual thunking.

If we force strictness all the way down it's not really call-by-value either, because the caller doesn't know what to evaluate (I think).

In addition, making pattern matching strict in this way makes it hard to mix and match strict and lazy data types (e.g. Maybe), because using a lazy data type from another module will make it appear strict in your code (hurting modularity).

On Fri, Dec 11, 2015 at 7:54 AM, Roman Cheplyaka <[hidden email]> wrote:
On 12/10/2015 04:34 PM, Johan Tibell wrote:
> I'm snowed under but I promise I will try to reply soon! To think about
> in the mean time: what do existing strict languages with pattern
> matching do?

Well, strict languages do not have lazy data to force to begin with, do they?

Personally, I find the simple intuition of "all patterns are strict by default" rather appealing.

E.g. I wouldn't expect the expressions

  let (v1,v2) = a in f v2

and

  let (v1,v2) = a; v3 = v2 in f v3

to have different semantics.

If we decide to adopt this semantics, we need to address the meaning of the pattern

  ~(v1, v2)

under -XStrict. Intuitively, ~ should propagate to the subpatterns. An alternative is to disallow this pattern under -XStrict and require writing all ~s explicitly, which may get tedious:

  ~(~v1, ~v2)
  ~(~v1, ~(~v2, ~v3))
  etc.

We also need to ensure the consistency between this extension and the unlifted data types proposal [1], given their similarity. Interestingly, I don't see constructor patterns explained there either.

[1]: https://ghc.haskell.org/trac/ghc/wiki/UnliftedDataTypes#Dynamicsemanticsofunliftedtypes



_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs



_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Roman Cheplyaka-2
On 12/11/2015 02:21 PM, Johan Tibell wrote:
> If we force strictness all the way down it's not really call-by-value
> either, because the caller doesn't know what to evaluate (I think).

Not sure what you mean here.

> In addition, making pattern matching strict in this way makes it hard to
> mix and match strict and lazy data types (e.g. Maybe), because using a
> lazy data type from another module will make it appear strict in your
> code (hurting modularity).

I don't think this is a case about modularity. A lazy Maybe value
defined in a lazy module remains lazy; and you can pass it to lazy
functions without forcing it. Only when you pattern match on it *in the
strict module*, the evaluation happens.

As I said, I prefer this semantics mainly because it's easier to
explain: all variables (and underscores) bound in a strict module refer
to WHNF values. Do you have a similarly simple explanation for the
semantics you're suggesting?

Roman


_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Ömer Sinan Ağacan
I agree with Roman here.

Probably another reason for making every binding strict is this: (sorry if this
is mentioned)

Suppose I imported `data D = D ...` from another library and I'm in -XStrict.
In this code:

    case ... of
      D b1 b2 ... -> <body>

I should be able to assume that b1, b2 ... etc. are all strict(that is, WHNF in
<body>) becuase I'm in -XStrict. This also makes the behavior more consistent,
I think.

2015-12-11 7:57 GMT-05:00 Roman Cheplyaka <[hidden email]>:

> On 12/11/2015 02:21 PM, Johan Tibell wrote:
>> If we force strictness all the way down it's not really call-by-value
>> either, because the caller doesn't know what to evaluate (I think).
>
> Not sure what you mean here.
>
>> In addition, making pattern matching strict in this way makes it hard to
>> mix and match strict and lazy data types (e.g. Maybe), because using a
>> lazy data type from another module will make it appear strict in your
>> code (hurting modularity).
>
> I don't think this is a case about modularity. A lazy Maybe value
> defined in a lazy module remains lazy; and you can pass it to lazy
> functions without forcing it. Only when you pattern match on it *in the
> strict module*, the evaluation happens.
>
> As I said, I prefer this semantics mainly because it's easier to
> explain: all variables (and underscores) bound in a strict module refer
> to WHNF values. Do you have a similarly simple explanation for the
> semantics you're suggesting?
>
> Roman
>
>
> _______________________________________________
> ghc-devs mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
>
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

RE: -XStrict: Why some binders are not made strict?

Simon Peyton Jones
In reply to this post by Roman Cheplyaka-2
| As I said, I prefer this semantics mainly because it's easier to
| explain: all variables (and underscores) bound in a strict module refer
| to WHNF values. Do you have a similarly simple explanation for the
| semantics you're suggesting?

Here's one, which is roughly what the current implementation does (modulo bugs):

* Code compiled under -XStrict constructs no thunks.

So consider

        module M1 where data T = C Int Int
        module M2 where f n = C (n+1) (n-1)
        module M3 where g x = let C y z = f x in ...

Look at M3.  Usually we'd get a thunk for (f 4), but not with -XStrict.  But even with -XStrict in M3, y,z might be bound to thunks.  

If you compile M2 with -XStrict, function f won't build thunks for (n+1), (n-1) but will evaluate them instead.

If you compile M1 with StrictData, then C is made strict, so again M2 will build no thunks even if M2 was compiled without -XStrict.

I quite like this design.  It's not clear to me that anything useful is gained by forcing y and z in M3 before evaluating the body "...".


So Roman's design makes sense, but so does the implemented design (modulo any bugs).  The trouble is that the implemented design is not well described.

Simon

| -----Original Message-----
| From: ghc-devs [mailto:[hidden email]] On Behalf Of Roman
| Cheplyaka
| Sent: 11 December 2015 12:57
| To: Johan Tibell <[hidden email]>
| Cc: [hidden email]
| Subject: Re: -XStrict: Why some binders are not made strict?
|
| On 12/11/2015 02:21 PM, Johan Tibell wrote:
| > If we force strictness all the way down it's not really call-by-value
| > either, because the caller doesn't know what to evaluate (I think).
|
| Not sure what you mean here.
|
| > In addition, making pattern matching strict in this way makes it hard to
| > mix and match strict and lazy data types (e.g. Maybe), because using a
| > lazy data type from another module will make it appear strict in your
| > code (hurting modularity).
|
| I don't think this is a case about modularity. A lazy Maybe value
| defined in a lazy module remains lazy; and you can pass it to lazy
| functions without forcing it. Only when you pattern match on it *in the
| strict module*, the evaluation happens.
|
| As I said, I prefer this semantics mainly because it's easier to
| explain: all variables (and underscores) bound in a strict module refer
| to WHNF values. Do you have a similarly simple explanation for the
| semantics you're suggesting?
|
| Roman

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

RE: -XStrict: Why some binders are not made strict?

Simon Peyton Jones
In reply to this post by Johan Tibell-2

In addition, making pattern matching strict in this way makes it hard to mix and match strict and lazy data types (e.g. Maybe), because using a lazy data type from another module will make it appear strict in your code (hurting modularity).

 

I didn’t understand that.

 

Simon

 

From: ghc-devs [mailto:[hidden email]] On Behalf Of Johan Tibell
Sent: 11 December 2015 12:22
To: Roman Cheplyaka <[hidden email]>
Cc: [hidden email]
Subject: Re: -XStrict: Why some binders are not made strict?

 

I believe Scala has optional lazy values, but you could also consider in strict languages if you do manual thunking.

 

If we force strictness all the way down it's not really call-by-value either, because the caller doesn't know what to evaluate (I think).

 

In addition, making pattern matching strict in this way makes it hard to mix and match strict and lazy data types (e.g. Maybe), because using a lazy data type from another module will make it appear strict in your code (hurting modularity).

 

On Fri, Dec 11, 2015 at 7:54 AM, Roman Cheplyaka <[hidden email]> wrote:

On 12/10/2015 04:34 PM, Johan Tibell wrote:
> I'm snowed under but I promise I will try to reply soon! To think about
> in the mean time: what do existing strict languages with pattern
> matching do?

Well, strict languages do not have lazy data to force to begin with, do they?

Personally, I find the simple intuition of "all patterns are strict by default" rather appealing.

E.g. I wouldn't expect the expressions

  let (v1,v2) = a in f v2

and

  let (v1,v2) = a; v3 = v2 in f v3

to have different semantics.

If we decide to adopt this semantics, we need to address the meaning of the pattern

  ~(v1, v2)

under -XStrict. Intuitively, ~ should propagate to the subpatterns. An alternative is to disallow this pattern under -XStrict and require writing all ~s explicitly, which may get tedious:

  ~(~v1, ~v2)
  ~(~v1, ~(~v2, ~v3))
  etc.

We also need to ensure the consistency between this extension and the unlifted data types proposal [1], given their similarity. Interestingly, I don't see constructor patterns explained there either.

[1]: https://ghc.haskell.org/trac/ghc/wiki/UnliftedDataTypes#Dynamicsemanticsofunliftedtypes



_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

 


_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Roman Cheplyaka-2
In reply to this post by Simon Peyton Jones
Thanks Simon, this is an interesting and compelling interpretation. But
I'm wondering whether it is enough to specify the dynamic semantics
unambiguously.

Two examples:

1.

  let _ = undefined in ()

Intuitively, since we are talking about /strictness/, this should
evaluate to bottom. However, it seems that your rule also admits () as
an answer; it is equivalent to () under lazy evaluation *and* it does
not create any thunks.

2.

  f g = g undefined

When compiled lazily, this code doesn't construct any thunks:

  f = \r srt:SRT:[02v :-> undefined] [g_suM] g_suM undefined;

So, under your rule, this is an admissible code for -XStrict, too. But
we can hardly call it strict.

On 12/12/2015 12:38 AM, Simon Peyton Jones wrote:

> | As I said, I prefer this semantics mainly because it's easier to
> | explain: all variables (and underscores) bound in a strict module refer
> | to WHNF values. Do you have a similarly simple explanation for the
> | semantics you're suggesting?
>
> Here's one, which is roughly what the current implementation does (modulo bugs):
>
> * Code compiled under -XStrict constructs no thunks.
>
> So consider
>
> module M1 where data T = C Int Int
> module M2 where f n = C (n+1) (n-1)
> module M3 where g x = let C y z = f x in ...
>
> Look at M3.  Usually we'd get a thunk for (f 4), but not with -XStrict.  But even with -XStrict in M3, y,z might be bound to thunks.  
>
> If you compile M2 with -XStrict, function f won't build thunks for (n+1), (n-1) but will evaluate them instead.
>
> If you compile M1 with StrictData, then C is made strict, so again M2 will build no thunks even if M2 was compiled without -XStrict.
>
> I quite like this design.  It's not clear to me that anything useful is gained by forcing y and z in M3 before evaluating the body "...".
>
>
> So Roman's design makes sense, but so does the implemented design (modulo any bugs).  The trouble is that the implemented design is not well described.
>
> Simon
>
> | -----Original Message-----
> | From: ghc-devs [mailto:[hidden email]] On Behalf Of Roman
> | Cheplyaka
> | Sent: 11 December 2015 12:57
> | To: Johan Tibell <[hidden email]>
> | Cc: [hidden email]
> | Subject: Re: -XStrict: Why some binders are not made strict?
> |
> | On 12/11/2015 02:21 PM, Johan Tibell wrote:
> | > If we force strictness all the way down it's not really call-by-value
> | > either, because the caller doesn't know what to evaluate (I think).
> |
> | Not sure what you mean here.
> |
> | > In addition, making pattern matching strict in this way makes it hard to
> | > mix and match strict and lazy data types (e.g. Maybe), because using a
> | > lazy data type from another module will make it appear strict in your
> | > code (hurting modularity).
> |
> | I don't think this is a case about modularity. A lazy Maybe value
> | defined in a lazy module remains lazy; and you can pass it to lazy
> | functions without forcing it. Only when you pattern match on it *in the
> | strict module*, the evaluation happens.
> |
> | As I said, I prefer this semantics mainly because it's easier to
> | explain: all variables (and underscores) bound in a strict module refer
> | to WHNF values. Do you have a similarly simple explanation for the
> | semantics you're suggesting?
> |
> | Roman
>


_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Adam Sandberg Eriksson
Hello,

Given the upcoming 8.0 feature freeze I think the correct approach for
8.0 is to document the current implementation (I'll try to do that this
week).

It would probably be good if interested parties would document their
input in a ticket.

Cheers,
--Adam


On Sat, 12 Dec 2015, at 12:55 AM, Roman Cheplyaka wrote:

> Thanks Simon, this is an interesting and compelling interpretation. But
> I'm wondering whether it is enough to specify the dynamic semantics
> unambiguously.
>
> Two examples:
>
> 1.
>
>   let _ = undefined in ()
>
> Intuitively, since we are talking about /strictness/, this should
> evaluate to bottom. However, it seems that your rule also admits () as
> an answer; it is equivalent to () under lazy evaluation *and* it does
> not create any thunks.
>
> 2.
>
>   f g = g undefined
>
> When compiled lazily, this code doesn't construct any thunks:
>
>   f = \r srt:SRT:[02v :-> undefined] [g_suM] g_suM undefined;
>
> So, under your rule, this is an admissible code for -XStrict, too. But
> we can hardly call it strict.
>
> On 12/12/2015 12:38 AM, Simon Peyton Jones wrote:
> > | As I said, I prefer this semantics mainly because it's easier to
> > | explain: all variables (and underscores) bound in a strict module refer
> > | to WHNF values. Do you have a similarly simple explanation for the
> > | semantics you're suggesting?
> >
> > Here's one, which is roughly what the current implementation does (modulo bugs):
> >
> > * Code compiled under -XStrict constructs no thunks.
> >
> > So consider
> >
> > module M1 where data T = C Int Int
> > module M2 where f n = C (n+1) (n-1)
> > module M3 where g x = let C y z = f x in ...
> >
> > Look at M3.  Usually we'd get a thunk for (f 4), but not with -XStrict.  But even with -XStrict in M3, y,z might be bound to thunks.  
> >
> > If you compile M2 with -XStrict, function f won't build thunks for (n+1), (n-1) but will evaluate them instead.
> >
> > If you compile M1 with StrictData, then C is made strict, so again M2 will build no thunks even if M2 was compiled without -XStrict.
> >
> > I quite like this design.  It's not clear to me that anything useful is gained by forcing y and z in M3 before evaluating the body "...".
> >
> >
> > So Roman's design makes sense, but so does the implemented design (modulo any bugs).  The trouble is that the implemented design is not well described.
> >
> > Simon
> >
> > | -----Original Message-----
> > | From: ghc-devs [mailto:[hidden email]] On Behalf Of Roman
> > | Cheplyaka
> > | Sent: 11 December 2015 12:57
> > | To: Johan Tibell <[hidden email]>
> > | Cc: [hidden email]
> > | Subject: Re: -XStrict: Why some binders are not made strict?
> > |
> > | On 12/11/2015 02:21 PM, Johan Tibell wrote:
> > | > If we force strictness all the way down it's not really call-by-value
> > | > either, because the caller doesn't know what to evaluate (I think).
> > |
> > | Not sure what you mean here.
> > |
> > | > In addition, making pattern matching strict in this way makes it hard to
> > | > mix and match strict and lazy data types (e.g. Maybe), because using a
> > | > lazy data type from another module will make it appear strict in your
> > | > code (hurting modularity).
> > |
> > | I don't think this is a case about modularity. A lazy Maybe value
> > | defined in a lazy module remains lazy; and you can pass it to lazy
> > | functions without forcing it. Only when you pattern match on it *in the
> > | strict module*, the evaluation happens.
> > |
> > | As I said, I prefer this semantics mainly because it's easier to
> > | explain: all variables (and underscores) bound in a strict module refer
> > | to WHNF values. Do you have a similarly simple explanation for the
> > | semantics you're suggesting?
> > |
> > | Roman
> >
>
>
> _______________________________________________
> ghc-devs mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
> Email had 1 attachment:
> + signature.asc
>   1k (application/pgp-signature)
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: -XStrict: Why some binders are not made strict?

Johan Tibell-2
Agreed.

(Sorry for the sporadic communication. This is a very busy time at work.)

I thought about this a bit more recently.

Here's one way where I think "force every binder" goes wrong:

-- In a Strict module
f (Just x) = Just x

This is not the identity. This might matter in practice if a user defines a data type, in a lazy module, that uses a lazy field to cache an expensive calculation:

-- In a lazy module:
data CachedHash = CH a Int
mkCH x = CH x (expensiveHash x)

The intention here is that we only evaluate the expensive hash function when needed. However, if we evaluate every binder this is no longer transparent to users of the module, because doing this forces both fields:

f (CH x h) = CH x h

This also seems a bit "one sided" in that we do not evaluate expr in `Just <expr>` under Strict, to not break modularity, but we would do it if you pattern-matched on the contents of Just.

I'm also worried that we might make a choice here that we can't undo. I at least understand the meaning of Strict in relation to strict languages. "Evaluate every binder" is a new thing. Perhaps it deserves its own pragma, StrictBinders.

On Mon, Dec 14, 2015 at 6:50 PM, Adam Sandberg Eriksson <[hidden email]> wrote:
Hello,

Given the upcoming 8.0 feature freeze I think the correct approach for
8.0 is to document the current implementation (I'll try to do that this
week).

It would probably be good if interested parties would document their
input in a ticket.

Cheers,
--Adam


On Sat, 12 Dec 2015, at 12:55 AM, Roman Cheplyaka wrote:
> Thanks Simon, this is an interesting and compelling interpretation. But
> I'm wondering whether it is enough to specify the dynamic semantics
> unambiguously.
>
> Two examples:
>
> 1.
>
>   let _ = undefined in ()
>
> Intuitively, since we are talking about /strictness/, this should
> evaluate to bottom. However, it seems that your rule also admits () as
> an answer; it is equivalent to () under lazy evaluation *and* it does
> not create any thunks.
>
> 2.
>
>   f g = g undefined
>
> When compiled lazily, this code doesn't construct any thunks:
>
>   f = \r srt:SRT:[02v :-> undefined] [g_suM] g_suM undefined;
>
> So, under your rule, this is an admissible code for -XStrict, too. But
> we can hardly call it strict.
>
> On 12/12/2015 12:38 AM, Simon Peyton Jones wrote:
> > | As I said, I prefer this semantics mainly because it's easier to
> > | explain: all variables (and underscores) bound in a strict module refer
> > | to WHNF values. Do you have a similarly simple explanation for the
> > | semantics you're suggesting?
> >
> > Here's one, which is roughly what the current implementation does (modulo bugs):
> >
> > * Code compiled under -XStrict constructs no thunks.
> >
> > So consider
> >
> >     module M1 where data T = C Int Int
> >     module M2 where f n = C (n+1) (n-1)
> >     module M3 where g x = let C y z = f x in ...
> >
> > Look at M3.  Usually we'd get a thunk for (f 4), but not with -XStrict.  But even with -XStrict in M3, y,z might be bound to thunks.
> >
> > If you compile M2 with -XStrict, function f won't build thunks for (n+1), (n-1) but will evaluate them instead.
> >
> > If you compile M1 with StrictData, then C is made strict, so again M2 will build no thunks even if M2 was compiled without -XStrict.
> >
> > I quite like this design.  It's not clear to me that anything useful is gained by forcing y and z in M3 before evaluating the body "...".
> >
> >
> > So Roman's design makes sense, but so does the implemented design (modulo any bugs).  The trouble is that the implemented design is not well described.
> >
> > Simon
> >
> > | -----Original Message-----
> > | From: ghc-devs [mailto:[hidden email]] On Behalf Of Roman
> > | Cheplyaka
> > | Sent: 11 December 2015 12:57
> > | To: Johan Tibell <[hidden email]>
> > | Cc: [hidden email]
> > | Subject: Re: -XStrict: Why some binders are not made strict?
> > |
> > | On 12/11/2015 02:21 PM, Johan Tibell wrote:
> > | > If we force strictness all the way down it's not really call-by-value
> > | > either, because the caller doesn't know what to evaluate (I think).
> > |
> > | Not sure what you mean here.
> > |
> > | > In addition, making pattern matching strict in this way makes it hard to
> > | > mix and match strict and lazy data types (e.g. Maybe), because using a
> > | > lazy data type from another module will make it appear strict in your
> > | > code (hurting modularity).
> > |
> > | I don't think this is a case about modularity. A lazy Maybe value
> > | defined in a lazy module remains lazy; and you can pass it to lazy
> > | functions without forcing it. Only when you pattern match on it *in the
> > | strict module*, the evaluation happens.
> > |
> > | As I said, I prefer this semantics mainly because it's easier to
> > | explain: all variables (and underscores) bound in a strict module refer
> > | to WHNF values. Do you have a similarly simple explanation for the
> > | semantics you're suggesting?
> > |
> > | Roman
> >
>
>
> _______________________________________________
> ghc-devs mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
> Email had 1 attachment:
> + signature.asc
>   1k (application/pgp-signature)


_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

RE: -XStrict: Why some binders are not made strict?

Simon Peyton Jones
In reply to this post by Adam Sandberg Eriksson
| Given the upcoming 8.0 feature freeze I think the correct approach for
| 8.0 is to document the current implementation (I'll try to do that this
| week).

Yes, that's right.  Thanks!

Simon


|
| It would probably be good if interested parties would document their
| input in a ticket.
|
| Cheers,
| --Adam
|
|
| On Sat, 12 Dec 2015, at 12:55 AM, Roman Cheplyaka wrote:
| > Thanks Simon, this is an interesting and compelling interpretation. But
| > I'm wondering whether it is enough to specify the dynamic semantics
| > unambiguously.
| >
| > Two examples:
| >
| > 1.
| >
| >   let _ = undefined in ()
| >
| > Intuitively, since we are talking about /strictness/, this should
| > evaluate to bottom. However, it seems that your rule also admits () as
| > an answer; it is equivalent to () under lazy evaluation *and* it does
| > not create any thunks.
| >
| > 2.
| >
| >   f g = g undefined
| >
| > When compiled lazily, this code doesn't construct any thunks:
| >
| >   f = \r srt:SRT:[02v :-> undefined] [g_suM] g_suM undefined;
| >
| > So, under your rule, this is an admissible code for -XStrict, too. But
| > we can hardly call it strict.
| >
| > On 12/12/2015 12:38 AM, Simon Peyton Jones wrote:
| > > | As I said, I prefer this semantics mainly because it's easier to
| > > | explain: all variables (and underscores) bound in a strict module refer
| > > | to WHNF values. Do you have a similarly simple explanation for the
| > > | semantics you're suggesting?
| > >
| > > Here's one, which is roughly what the current implementation does (modulo
| bugs):
| > >
| > > * Code compiled under -XStrict constructs no thunks.
| > >
| > > So consider
| > >
| > > module M1 where data T = C Int Int
| > > module M2 where f n = C (n+1) (n-1)
| > > module M3 where g x = let C y z = f x in ...
| > >
| > > Look at M3.  Usually we'd get a thunk for (f 4), but not with -XStrict.
| But even with -XStrict in M3, y,z might be bound to thunks.
| > >
| > > If you compile M2 with -XStrict, function f won't build thunks for (n+1),
| (n-1) but will evaluate them instead.
| > >
| > > If you compile M1 with StrictData, then C is made strict, so again M2
| will build no thunks even if M2 was compiled without -XStrict.
| > >
| > > I quite like this design.  It's not clear to me that anything useful is
| gained by forcing y and z in M3 before evaluating the body "...".
| > >
| > >
| > > So Roman's design makes sense, but so does the implemented design (modulo
| any bugs).  The trouble is that the implemented design is not well described.
| > >
| > > Simon
| > >
| > > | -----Original Message-----
| > > | From: ghc-devs [mailto:[hidden email]] On Behalf Of Roman
| > > | Cheplyaka
| > > | Sent: 11 December 2015 12:57
| > > | To: Johan Tibell <[hidden email]>
| > > | Cc: [hidden email]
| > > | Subject: Re: -XStrict: Why some binders are not made strict?
| > > |
| > > | On 12/11/2015 02:21 PM, Johan Tibell wrote:
| > > | > If we force strictness all the way down it's not really call-by-value
| > > | > either, because the caller doesn't know what to evaluate (I think).
| > > |
| > > | Not sure what you mean here.
| > > |
| > > | > In addition, making pattern matching strict in this way makes it hard
| to
| > > | > mix and match strict and lazy data types (e.g. Maybe), because using
| a
| > > | > lazy data type from another module will make it appear strict in your
| > > | > code (hurting modularity).
| > > |
| > > | I don't think this is a case about modularity. A lazy Maybe value
| > > | defined in a lazy module remains lazy; and you can pass it to lazy
| > > | functions without forcing it. Only when you pattern match on it *in the
| > > | strict module*, the evaluation happens.
| > > |
| > > | As I said, I prefer this semantics mainly because it's easier to
| > > | explain: all variables (and underscores) bound in a strict module refer
| > > | to WHNF values. Do you have a similarly simple explanation for the
| > > | semantics you're suggesting?
| > > |
| > > | Roman
| > >
| >
| >
| > _______________________________________________
| > ghc-devs mailing list
| > [hidden email]
| >
| https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.haskell.
| org%2fcgi-bin%2fmailman%2flistinfo%2fghc-
| devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c81ebe250762640019a7b08
| d304af0dcc%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=qy2g8Dy4zDVKohNOHLnYT
| ekaVLtckBwTtOvN6y4cUuo%3d
| > Email had 1 attachment:
| > + signature.asc
| >   1k (application/pgp-signature)
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

RE: -XStrict: Why some binders are not made strict?

Simon Peyton Jones
In reply to this post by Roman Cheplyaka-2
|  Thanks Simon, this is an interesting and compelling interpretation.
|  But I'm wondering whether it is enough to specify the dynamic
|  semantics unambiguously.

You make good points.  Also, consider

        f (g x)

where f is define in some other (lazy) module.  Is that done call-by value?  That is, is (g x) evaluated before the call?  According to the current spec, no. So a thunk is built!

But if we write

        let y = g x in f y

then, lo, the (g x) is computed eagerly.

So the present semantics seems to be more
        functions always evaluate their arguments to
      WHNF (but not to NF)!

I do think this could do with a tighter spec.  Johan, Adam, this is your baby.

Simon


|  -----Original Message-----
|  From: Roman Cheplyaka [mailto:[hidden email]]
|  Sent: 11 December 2015 23:56
|  To: Simon Peyton Jones <[hidden email]>; Johan Tibell
|  <[hidden email]>
|  Cc: [hidden email]
|  Subject: Re: -XStrict: Why some binders are not made strict?
|  
|  Thanks Simon, this is an interesting and compelling interpretation.
|  But I'm wondering whether it is enough to specify the dynamic
|  semantics unambiguously.
|  
|  Two examples:
|  
|  1.
|  
|    let _ = undefined in ()
|  
|  Intuitively, since we are talking about /strictness/, this should
|  evaluate to bottom. However, it seems that your rule also admits () as
|  an answer; it is equivalent to () under lazy evaluation *and* it does
|  not create any thunks.
|  
|  2.
|  
|    f g = g undefined
|  
|  When compiled lazily, this code doesn't construct any thunks:
|  
|    f = \r srt:SRT:[02v :-> undefined] [g_suM] g_suM undefined;
|  
|  So, under your rule, this is an admissible code for -XStrict, too. But
|  we can hardly call it strict.
|  
|  On 12/12/2015 12:38 AM, Simon Peyton Jones wrote:
|  > | As I said, I prefer this semantics mainly because it's easier to
|  > | explain: all variables (and underscores) bound in a strict module
|  > | refer to WHNF values. Do you have a similarly simple explanation
|  for
|  > | the semantics you're suggesting?
|  >
|  > Here's one, which is roughly what the current implementation does
|  (modulo bugs):
|  >
|  > * Code compiled under -XStrict constructs no thunks.
|  >
|  > So consider
|  >
|  > module M1 where data T = C Int Int
|  > module M2 where f n = C (n+1) (n-1)
|  > module M3 where g x = let C y z = f x in ...
|  >
|  > Look at M3.  Usually we'd get a thunk for (f 4), but not with -
|  XStrict.  But even with -XStrict in M3, y,z might be bound to thunks.
|  >
|  > If you compile M2 with -XStrict, function f won't build thunks for
|  (n+1), (n-1) but will evaluate them instead.
|  >
|  > If you compile M1 with StrictData, then C is made strict, so again
|  M2 will build no thunks even if M2 was compiled without -XStrict.
|  >
|  > I quite like this design.  It's not clear to me that anything useful
|  is gained by forcing y and z in M3 before evaluating the body "...".
|  >
|  >
|  > So Roman's design makes sense, but so does the implemented design
|  (modulo any bugs).  The trouble is that the implemented design is not
|  well described.
|  >
|  > Simon
|  >
|  > | -----Original Message-----
|  > | From: ghc-devs [mailto:[hidden email]] On Behalf Of
|  > | Roman Cheplyaka
|  > | Sent: 11 December 2015 12:57
|  > | To: Johan Tibell <[hidden email]>
|  > | Cc: [hidden email]
|  > | Subject: Re: -XStrict: Why some binders are not made strict?
|  > |
|  > | On 12/11/2015 02:21 PM, Johan Tibell wrote:
|  > | > If we force strictness all the way down it's not really
|  > | > call-by-value either, because the caller doesn't know what to
|  evaluate (I think).
|  > |
|  > | Not sure what you mean here.
|  > |
|  > | > In addition, making pattern matching strict in this way makes it
|  > | > hard to mix and match strict and lazy data types (e.g. Maybe),
|  > | > because using a lazy data type from another module will make it
|  > | > appear strict in your code (hurting modularity).
|  > |
|  > | I don't think this is a case about modularity. A lazy Maybe value
|  > | defined in a lazy module remains lazy; and you can pass it to lazy
|  > | functions without forcing it. Only when you pattern match on it
|  *in
|  > | the strict module*, the evaluation happens.
|  > |
|  > | As I said, I prefer this semantics mainly because it's easier to
|  > | explain: all variables (and underscores) bound in a strict module
|  > | refer to WHNF values. Do you have a similarly simple explanation
|  for
|  > | the semantics you're suggesting?
|  > |
|  > | Roman
|  >
|  

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs