<div dir="ltr"><div>I'll raise a bug with all the details when I next get to a computer, probably tonight. A lint extension would be great for tracking this down.</div><div><br></div><div>I appreciate that there are good reasons for pushing ahead with a release, but there are three reasons that give me a little hesitation.</div><div><br></div>1) It may well be that this bug has been around for a while, and the trigger conditions are exceptionally difficult to hit, and going ahead seems fine. Or it's a regression introduced recently and Shake is just the tip of the iceberg. I don't think there is any way to tell yet. <div><br></div><div>2) The failure mode seems to be that programs just do the wrong thing, seemingly an unexpected jump to somewhere else. That can often be incredibly hard to spot - I have one test that catches it, but Shake has more tests than implementation - other programs may suffer and not realise. If the error mode really is "should have thrown an exception but continues somewhere else instead" there is even potential for that to be a security hole.</div><div><br></div><div>3) I tested with GHC RC1 and GHC RC2, both of which were fine. The fact no one else hit this with RC2 might just be because its a very recent regression.</div><div><br></div><div>Thanks, Neil <br><br>On Friday, 20 March 2015, Simon Peyton Jones <<a href="mailto:simonpj@microsoft.com" target="_blank">simonpj@microsoft.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">| FWIW, I've been noodling over this today since I saw this email, and<br>
| sitting down, I think this may be a blocker worth holding up for after<br>
| thinking about it. At least, it is until we can quantify how much it<br>
| might bite (can we find a workaround? How often does it hit in<br>
| practice?)<br>
<br>
I'm reluctant to delay 7.10 further.  I'm sure there are other bugs, and we'll want 7.10.2 before too long.   But we won't find them until we push it out.  The danger is that we stay in about-to-release mode for ages, and that holds everyone up.  We've had three release candidates out over a period of months and Neil seems to be the only one who has tripped over it.<br>
<br>
I think it'd be better to push it out.  (We planned to do so today!)  What do others think?<br>
<br>
Simon<br>
<br>
| -----Original Message-----<br>
| From: <a>mad.one@gmail.com</a> [mailto:<a>mad.one@gmail.com</a>] On Behalf Of Austin<br>
| Seipp<br>
| Sent: 20 March 2015 22:48<br>
| To: Herbert Valerio Riedel<br>
| Cc: Simon Peyton Jones; Austin Seipp<br>
| Subject: Re: Shake fails test with GHC 7.10 RC3<br>
|<br>
| FWIW, I've been noodling over this today since I saw this email, and<br>
| sitting down, I think this may be a blocker worth holding up for after<br>
| thinking about it. At least, it is until we can quantify how much it<br>
| might bite (can we find a workaround? How often does it hit in<br>
| practice?)<br>
|<br>
| I'm testing Iavor's patches that he wanted in at the last minute (I'm<br>
| really hesitant for that, since we could break something), so we've<br>
| got some time, but I'd like to at least narrow this down a bit more.<br>
|<br>
| On Fri, Mar 20, 2015 at 12:37 PM, Herbert Valerio Riedel<br>
| <<a>hvriedel@gmail.com</a>> wrote:<br>
| ><br>
| > ...does this in any way affect today's GHC 7.10.1 release? I.e. is this<br>
| > blocking the release?<br>
| ><br>
| ><br>
| > On 2015-03-20 at 18:19:09 +0100, Simon Peyton Jones wrote:<br>
| >> Neil<br>
| >><br>
| >> Could you open a ticket for this, and attach the info to it?  Lots of<br>
| useful info in this thread, but may get lost.<br>
| >><br>
| >> Re empty cases, see Note [Empty case alternatives] in CoreSyn.  "A<br>
| >> case expression can have empty alternatives if (and only if) the<br>
| >> scrutinee is bound to raise an exception or diverge."<br>
| >><br>
| >> So yes, case (\_ -> ...) of {} is definitely wrong.  Could someone<br>
| >> extend Core Lint to check for this?  The function to call is<br>
| >> exprIsHNF: if we have<br>
| >>       case e of {}<br>
| >> then exprIsHNF should never return True.<br>
| >><br>
| >> That is a powerful clue, and adding it to Lint will nail the moment at<br>
| which it first happens.  Good progress.<br>
| >><br>
| >> (I'd do it myself but I'm struggling with backlog, and only have 3<br>
| days left before going on holiday for 10 days.)<br>
| >><br>
| >> Simon<br>
| >><br>
| >> |  -----Original Message-----<br>
| >> |  From: Neil Mitchell [mailto:<a>ndmitchell@gmail.com</a>]<br>
| >> |  Sent: 20 March 2015 16:57<br>
| >> |  To: Carter Schonwald<br>
| >> |  Cc: Simon Peyton Jones; <a>ghc-devs@haskell.org</a><br>
| >> |  Subject: Re: Shake fails test with GHC 7.10 RC3<br>
| >> |<br>
| >> |  > do you use a deepSeq when catching errors from a pure<br>
| computation? Or<br>
| >> |  > is it in a context where you know the value should be treated<br>
| strictly?<br>
| >> |<br>
| >> |  The computation is essentially (error "here" :: IO ()), so the IO<br>
| monadic<br>
| >> |  binding should force the exception. In the full source code to<br>
| Shake it's<br>
| >> |  actually in ContT/ReaderT/IO, but a modification to insert liftIO<br>
| (if<br>
| >> |  done in exactly the right way) gives the same result. That<br>
| simplified<br>
| >> |  code is at <a href="http://community.haskell.org/~ndm/temp/src.zip" target="_blank">http://community.haskell.org/~ndm/temp/src.zip</a><br>
| >> |  (to run, compile with the logic from<br>
| >> |  <a href="https://github.com/ndmitchell/shake/blob/master/.ghci" target="_blank">https://github.com/ndmitchell/shake/blob/master/.ghci</a> :benchmark,<br>
| then<br>
| >> |  run "main oracle test").<br>
| >> |<br>
| >> |  > <a href="https://github.com/ndmitchell/shake/issues/216" target="_blank">https://github.com/ndmitchell/shake/issues/216</a> seems to be the<br>
| ticket<br>
| >> |  > in question<br>
| >> |<br>
| >> |  That is the ticket. The test that is failing is the "oracle"<br>
| >> |  (Test.Oracle) test suite, and you can see full logs of both success<br>
| and<br>
| >> |  failure at Travis:<br>
| >> |  <a href="https://travis-ci.org/ndmitchell/shake/builds/54748475" target="_blank">https://travis-ci.org/ndmitchell/shake/builds/54748475</a> . Note that<br>
| it<br>
| >> |  succeeds on GHC 7.2, 7.4, 7.6 and 7.8, but fails on GHC 7.10 RC3<br>
| and GHC<br>
| >> |  Head.<br>
| >> |<br>
| >> |  Alas, the actual error is coming from deep in the middle of Shake,<br>
| >> |  specifically this line:<br>
| >> |<br>
| <a href="https://github.com/ndmitchell/shake/blob/master/src/Development/Shake/Cor" target="_blank">https://github.com/ndmitchell/shake/blob/master/src/Development/Shake/Cor</a><br>
| >> |  e.hs#L329<br>
| >> |<br>
| >> |  Thinking some more on what I saw, my best guess is that:<br>
| >> |<br>
| >> |  case (\_ -> ...) of {}<br>
| >> |<br>
| >> |  Is a fatal error in GHC. I am guessing that {} means there are no<br>
| >> |  alternatives because GHC managed to show that the scrutinee throws<br>
| an<br>
| >> |  exception. In addition, evaluating a literal lambda to WHNF will<br>
| not<br>
| >> |  throw an exception, so you have a contradiction.<br>
| >> |<br>
| >> |  Making increasingly wild speculative guesses, I could imagine this<br>
| code<br>
| >> |  compiling to CMM that just fell off the end of a basic block,<br>
| arriving at<br>
| >> |  the next statement of supposedly unconnected code. That actually<br>
| matches<br>
| >> |  what I'm seeing - I have the exception, using print I can see I am<br>
| at the<br>
| >> |  line before, and that I never get to the line after, but pop up<br>
| somewhere<br>
| >> |  nearby and continue onwards seemingly ignoring the exception ever<br>
| >> |  happened.<br>
| >> |<br>
| >> |  If someone can confirm the above pattern of Core is always illegal<br>
| and<br>
| >> |  always indicates a GHC error then I can reduce the test case driven<br>
| >> |  purely by the Core, which would be far easier - at the moment Shake<br>
| >> |  passes through these routines several times to set things up,<br>
| making it<br>
| >> |  harder to simplify them too much without changing the preparation<br>
| steps.<br>
| >> |<br>
| >> |  Thanks, Neil<br>
| >> |<br>
| >> |<br>
| >> |  >><br>
| >> |  >> On Fri, Mar 20, 2015 at 12:01 AM, Neil Mitchell<br>
| >> |  >> <<a>ndmitchell@gmail.com</a>><br>
| >> |  >> wrote:<br>
| >> |  >> > More delving later, it seems the incorrect optimized version<br>
| has<br>
| >> |  >> > been turned into:<br>
| >> |  >> ><br>
| >> |  >> > case (\ _ [Occ=Dead, OS=OneShot] -> error "here") of _<br>
| [Occ=Dead]<br>
| >> |  >> > {}<br>
| >> |  >> ><br>
| >> |  >> > While the working one has been turned into:<br>
| >> |  >> ><br>
| >> |  >> > errorFunc argument realWorldToken<br>
| >> |  >> ><br>
| >> |  >> > where errorFunc _ = error "here"<br>
| >> |  >> ><br>
| >> |  >> > I'm not familiar with case ... of _ {} - what does it mean<br>
| when<br>
| >> |  >> > there are no alternatives to the case? And why isn't case on a<br>
| >> |  >> > literal lambda optimised out? Is it the OneShot annotation<br>
| (perhaps<br>
| >> |  >> > coming from the state hack?)<br>
| >> |  >> ><br>
| >> |  >> > The full trace is at<br>
| >> |  >> > <a href="https://gist.github.com/ndmitchell/b222e04eb0c3a397c758" target="_blank">https://gist.github.com/ndmitchell/b222e04eb0c3a397c758</a>. I've<br>
| >> |  >> > uploaded bad (optimises the error out) and good (works as<br>
| expected)<br>
| >> |  >> > versions of the Core. The summary files are the subexpression<br>
| that<br>
| >> |  >> > changed making a single difference (moving a monomorphic<br>
| NOINLINE<br>
| >> |  >> > function from one module to another) plus the handful of<br>
| functions<br>
| >> |  >> > they depend on, which I've reformatted/inlined/simplified to<br>
| produce<br>
| >> |  the expressions above.<br>
| >> |  >> > The full versions are the entire -ddump-simpl output from<br>
| about<br>
| >> |  >> > halfway through the build, starting when the differences occur<br>
| -<br>
| >> |  >> > let me know if you need further back. The dodgy function is<br>
| "exec".<br>
| >> |  >> ><br>
| >> |  >> > Thanks, Neil<br>
| >> |  >> ><br>
| >> |  >> > On Thu, Mar 19, 2015 at 11:07 PM, Neil Mitchell<br>
| >> |  >> > <<a>ndmitchell@gmail.com</a>><br>
| >> |  >> > wrote:<br>
| >> |  >> >> Herbert, thanks for the list of patches, nothing obvious<br>
| there -<br>
| >> |  >> >> my best guess is it's something incredibly sensitive and it<br>
| only<br>
| >> |  >> >> needs the tiniest change anywhere to make it happen. Things<br>
| like<br>
| >> |  >> >> moving NOINLINE monomorphic-type definitions from one module<br>
| to<br>
| >> |  >> >> another are causing the bug to appear/disappear, which isn't<br>
| what<br>
| >> |  I'd expect.<br>
| >> |  >> >><br>
| >> |  >> >> Simon, changing from error to error in IO causes the bug to<br>
| >> |  >> >> disappear, but then so do most things. The error return type<br>
| is<br>
| >> |  >> >> type IO (), so I suspect that forces it to be raised at the<br>
| right<br>
| >> |  >> >> place - but it's certainly one of the possibilities for what<br>
| is<br>
| >> |  >> >> going wrong. Diffing the Core is a great idea.<br>
| >> |  >> >><br>
| >> |  >> >> I'll keep reducing and see what I get to. Given the<br>
| sensitivity of<br>
| >> |  >> >> the bug, I'm sure a NOINLINE on an out-of-the-way function<br>
| will<br>
| >> |  >> >> make it go away, so I can easily fix Shake itself - so I'm<br>
| more<br>
| >> |  >> >> tracking it down from the point of GHC now.<br>
| >> |  >> >><br>
| >> |  >> >> Thanks, Neil<br>
| >> |  >> >><br>
| >> |  >> >><br>
| >> |  >> >> On Wed, Mar 18, 2015 at 5:04 PM, Simon Peyton Jones<br>
| >> |  >> >> <<a>simonpj@microsoft.com</a>> wrote:<br>
| >> |  >> >>> I'm really sorry but I can't think of anything.  Sounds<br>
| horrible.<br>
| >> |  >> >>><br>
| >> |  >> >>> If you throw exceptions using 'error' (not in IO), then you<br>
| are<br>
| >> |  >> >>> of course vulnerable to strictness changes.  If the thing<br>
| isn't<br>
| >> |  >> >>> actually evaluated inside the catch block, you won't see the<br>
| >> |  >> >>> exception.  But I'm sure you've thought of that.<br>
| >> |  >> >>><br>
| >> |  >> >>> I'd experiment with one of the smaller changes you describe,<br>
| such<br>
| >> |  >> >>> as adding a putStrLn, and comparing Core, before and after.<br>
| >> |  >> >>> Switching off -O will make a huge difference, so hard to<br>
| compare.<br>
| >> |  >> >>> Turning off the state hack will have a more global effect.<br>
| But<br>
| >> |  >> >>> the other changes sound more pin-point and hence the<br>
| differences<br>
| >> |  will be smaller.<br>
| >> |  >> >>><br>
| >> |  >> >>> Simon<br>
| >> |  >> >>><br>
| >> |  >> >>> |  -----Original Message-----<br>
| >> |  >> >>> |  From: ghc-devs [mailto:<a>ghc-devs-bounces@haskell.org</a>] On<br>
| Behalf<br>
| >> |  >> >>> | Of<br>
| >> |  >> >>> Neil<br>
| >> |  >> >>> |  Mitchell<br>
| >> |  >> >>> |  Sent: 18 March 2015 15:33<br>
| >> |  >> >>> |  To: <a>ghc-devs@haskell.org</a><br>
| >> |  >> >>> |  Subject: Shake fails test with GHC 7.10 RC3<br>
| >> |  >> >>> |<br>
| >> |  >> >>> |  Hi,<br>
| >> |  >> >>> |<br>
| >> |  >> >>> |  Testing GHC 7.10 RC3 I've found a bug where Shake seems<br>
| to<br>
| >> |  >> >>> | catch<br>
| >> |  >> >>> the<br>
| >> |  >> >>> |  wrong exception in the wrong place. It's only hit by one<br>
| of my<br>
| >> |  >> >>> tests,<br>
| >> |  >> >>> |  and I've managed to isolate it to a fragment of code with<br>
| no<br>
| >> |  >> >>> | unsafePerformIO, that throws exceptions using error (so<br>
| not in<br>
| >> |  >> >>> | IO),<br>
| >> |  >> >>> and<br>
| >> |  >> >>> |  operates in IO. Turning off the stack hack makes the bug<br>
| go<br>
| >> |  >> >>> | away,<br>
| >> |  >> >>> but<br>
| >> |  >> >>> |  then so does -O0, marking one of the functions it calls<br>
| >> |  >> >>> | NOINLINE,<br>
| >> |  >> >>> or<br>
| >> |  >> >>> |  moving an INLINE function it calls to a different module,<br>
| or<br>
| >> |  >> >>> | adding<br>
| >> |  >> >>> a<br>
| >> |  >> >>> |  putStrLn under a catch block - it's very sensitive to the<br>
| >> |  >> >>> | exact  conditions. This test and this exact code worked<br>
| fine<br>
| >> |  >> >>> | with GHC 7.10  RC2.<br>
| >> |  >> >>> |<br>
| >> |  >> >>> |  I was wondering if there have been any state hack related<br>
| >> |  >> >>> | changes<br>
| >> |  >> >>> or<br>
| >> |  >> >>> |  other potentially dangerous optimisation changes since<br>
| RC2?<br>
| >> |  >> >>> | I'll  continue to try reducing the bug, but it's somewhat<br>
| >> |  >> >>> | difficult as<br>
| >> |  >> >>> the<br>
| >> |  >> >>> |  larger system is quite big, and the code is very<br>
| sensitive.<br>
| >> |  >> >>> |<br>
| >> |  >> >>> |  Thanks, Neil<br>
| >> |  >> >>> |  _______________________________________________<br>
| >> |  >> >>> |  ghc-devs mailing list<br>
| >> |  >> >>> |  <a>ghc-devs@haskell.org</a><br>
| >> |  >> >>> |  <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><br>
| >> |  >> ><br>
| >> |  >> > On Thu, Mar 19, 2015 at 11:24 PM, Simon Peyton Jones<br>
| >> |  >> > <<a>simonpj@microsoft.com</a>> wrote:<br>
| >> |  >> >> Thanks!  I think a -ddump-simpl before and after the smallest<br>
| >> |  >> >> change the makes the difference would be illuminating.<br>
| >> |  >> >><br>
| >> |  >> >> Simon<br>
| >> |  >> >><br>
| >> |  >> >> | -----Original Message-----<br>
| >> |  >> >> | From: Neil Mitchell [mailto:<a>ndmitchell@gmail.com</a>]<br>
| >> |  >> >> | Sent: 19 March 2015 23:07<br>
| >> |  >> >> | To: Simon Peyton Jones<br>
| >> |  >> >> | Cc: <a>ghc-devs@haskell.org</a><br>
| >> |  >> >> | Subject: Re: Shake fails test with GHC 7.10 RC3<br>
| >> |  >> >> |<br>
| >> |  >> >> | Herbert, thanks for the list of patches, nothing obvious<br>
| there -<br>
| >> |  >> >> | my best guess is it's something incredibly sensitive and it<br>
| only<br>
| >> |  >> >> | needs the tiniest change anywhere to make it happen. Things<br>
| like<br>
| >> |  >> >> | moving NOINLINE monomorphic-type definitions from one<br>
| module to<br>
| >> |  >> >> | another are causing the bug to appear/disappear, which<br>
| isn't what<br>
| >> |  I'd expect.<br>
| >> |  >> >> |<br>
| >> |  >> >> | Simon, changing from error to error in IO causes the bug to<br>
| >> |  >> >> disappear,<br>
| >> |  >> >> | but then so do most things. The error return type is type<br>
| IO (),<br>
| >> |  >> >> | so I suspect that forces it to be raised at the right place<br>
| -<br>
| >> |  >> >> | but it's certainly one of the possibilities for what is<br>
| going<br>
| >> |  >> >> | wrong. Diffing the Core is a great idea.<br>
| >> |  >> >> |<br>
| >> |  >> >> | I'll keep reducing and see what I get to. Given the<br>
| sensitivity<br>
| >> |  >> >> | of<br>
| >> |  >> >> the<br>
| >> |  >> >> | bug, I'm sure a NOINLINE on an out-of-the-way function will<br>
| make<br>
| >> |  >> >> | it<br>
| >> |  >> >> go<br>
| >> |  >> >> | away, so I can easily fix Shake itself - so I'm more<br>
| tracking it<br>
| >> |  >> >> | down from the point of GHC now.<br>
| >> |  >> >> |<br>
| >> |  >> >> | Thanks, Neil<br>
| >> |  >> >> |<br>
| >> |  >> >> |<br>
| >> |  >> >> | On Wed, Mar 18, 2015 at 5:04 PM, Simon Peyton Jones<br>
| >> |  >> >> | <<a>simonpj@microsoft.com</a>> wrote:<br>
| >> |  >> >> | > I'm really sorry but I can't think of anything.  Sounds<br>
| >> |  horrible.<br>
| >> |  >> >> | ><br>
| >> |  >> >> | > If you throw exceptions using 'error' (not in IO), then<br>
| you<br>
| >> |  >> >> | > are of<br>
| >> |  >> >> | course vulnerable to strictness changes.  If the thing<br>
| isn't<br>
| >> |  >> >> | actually evaluated inside the catch block, you won't see<br>
| the<br>
| >> |  >> >> | exception.  But<br>
| >> |  >> >> I'm<br>
| >> |  >> >> | sure you've thought of that.<br>
| >> |  >> >> | ><br>
| >> |  >> >> | > I'd experiment with one of the smaller changes you<br>
| describe,<br>
| >> |  >> >> | > such<br>
| >> |  >> >> as<br>
| >> |  >> >> | adding a putStrLn, and comparing Core, before and after.<br>
| >> |  >> >> | Switching<br>
| >> |  >> >> off -<br>
| >> |  >> >> | O will make a huge difference, so hard to compare.  Turning<br>
| off<br>
| >> |  >> >> | the<br>
| >> |  >> >> state<br>
| >> |  >> >> | hack will have a more global effect.  But the other changes<br>
| >> |  >> >> | sound<br>
| >> |  >> >> more<br>
| >> |  >> >> | pin-point and hence the differences will be smaller.<br>
| >> |  >> >> | ><br>
| >> |  >> >> | > Simon<br>
| >> |  >> >> | ><br>
| >> |  >> >> | > |  -----Original Message-----<br>
| >> |  >> >> | > |  From: ghc-devs [mailto:<a>ghc-devs-bounces@haskell.org</a>]<br>
| On<br>
| >> |  >> >> | > | Behalf<br>
| >> |  >> >> Of<br>
| >> |  >> >> | Neil<br>
| >> |  >> >> | > |  Mitchell<br>
| >> |  >> >> | > |  Sent: 18 March 2015 15:33<br>
| >> |  >> >> | > |  To: <a>ghc-devs@haskell.org</a><br>
| >> |  >> >> | > |  Subject: Shake fails test with GHC 7.10 RC3<br>
| >> |  >> >> | > |<br>
| >> |  >> >> | > |  Hi,<br>
| >> |  >> >> | > |<br>
| >> |  >> >> | > |  Testing GHC 7.10 RC3 I've found a bug where Shake<br>
| seems to<br>
| >> |  >> >> | > | catch<br>
| >> |  >> >> the<br>
| >> |  >> >> | > |  wrong exception in the wrong place. It's only hit by<br>
| one of<br>
| >> |  >> >> | > | my<br>
| >> |  >> >> | tests,<br>
| >> |  >> >> | > |  and I've managed to isolate it to a fragment of code<br>
| with<br>
| >> |  >> >> | > | no  unsafePerformIO, that throws exceptions using error<br>
| (so<br>
| >> |  >> >> | > | not in<br>
| >> |  >> >> IO),<br>
| >> |  >> >> | and<br>
| >> |  >> >> | > |  operates in IO. Turning off the stack hack makes the<br>
| bug go<br>
| >> |  >> >> away,<br>
| >> |  >> >> | but<br>
| >> |  >> >> | > |  then so does -O0, marking one of the functions it<br>
| calls<br>
| >> |  >> >> NOINLINE, or<br>
| >> |  >> >> | > |  moving an INLINE function it calls to a different<br>
| module,<br>
| >> |  >> >> | > | or<br>
| >> |  >> >> adding<br>
| >> |  >> >> | a<br>
| >> |  >> >> | > |  putStrLn under a catch block - it's very sensitive to<br>
| the<br>
| >> |  >> >> | > | exact  conditions. This test and this exact code worked<br>
| fine<br>
| >> |  >> >> | > | with GHC<br>
| >> |  >> >> 7.10<br>
| >> |  >> >> | > |  RC2.<br>
| >> |  >> >> | > |<br>
| >> |  >> >> | > |  I was wondering if there have been any state hack<br>
| related<br>
| >> |  >> >> changes or<br>
| >> |  >> >> | > |  other potentially dangerous optimisation changes since<br>
| RC2?<br>
| >> |  >> >> | > | I'll  continue to try reducing the bug, but it's<br>
| somewhat<br>
| >> |  >> >> | > | difficult as<br>
| >> |  >> >> the<br>
| >> |  >> >> | > |  larger system is quite big, and the code is very<br>
| sensitive.<br>
| >> |  >> >> | > |<br>
| >> |  >> >> | > |  Thanks, Neil<br>
| >> |  >> >> | > |  _______________________________________________<br>
| >> |  >> >> | > |  ghc-devs mailing list<br>
| >> |  >> >> | > |  <a>ghc-devs@haskell.org</a><br>
| >> |  >> >> | > |  <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-</a><br>
| devs<br>
| >> |  >> _______________________________________________<br>
| >> |  >> ghc-devs mailing list<br>
| >> |  >> <a>ghc-devs@haskell.org</a><br>
| >> |  >> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><br>
| >> |  ><br>
| >> |  ><br>
| >> _______________________________________________<br>
| >> ghc-devs mailing list<br>
| >> <a>ghc-devs@haskell.org</a><br>
| >> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><br>
| ><br>
| > --<br>
| > "Elegance is not optional" -- Richard O'Keefe<br>
| ><br>
|<br>
|<br>
|<br>
| --<br>
| Regards,<br>
|<br>
| Austin Seipp, Haskell Consultant<br>
| Well-Typed LLP, <a href="http://www.well-typed.com/" target="_blank">http://www.well-typed.com/</a><br>
</blockquote></div>
</div>