[Haskell-cafe] GHC bug? Let with guards loops

Dan Doel dan.doel at gmail.com
Tue Jul 9 19:56:42 CEST 2013


With pattern guards, it's difficult to say whether it is never 'useful' to
have things like the following work:

    C x | C' y z <- f x = ...

But I'd also shy away from changing the behavior because it causes a lot of
consistency issues. In

    let
      f <vs1> | gs1 = es1
      h <vs2> | gs2 = es2
      ...

we have that f and h are in scope in both gs1 and gs2. Does it make sense
to call f in gs1? It's easy to loop if you do. So should f not be in scope
in gs1, but h is, and vice versa for gs2? But they're both in scope for es1
and es2?

And if we leave the above alone, then what about the case where there are
no <vs>? Is that different? Or is it only left-hand patterns that get this
treatment?

Also, it might have some weird consequences for moving code around. Like:

    let Just x | x > 0 = Just 1

    let Just x | y > 0 = Just 1
        y = x

    let Just x | b = Just 1
          where b = x > 0

    let Just x | b = Just 1
        b = x > 0

These all behave the same way now. Which ones should change?

If Haskell had a non-recursive let, that'd probably be a different story.
But it doesn't.



On Tue, Jul 9, 2013 at 1:12 PM, Andreas Abel <andreas.abel at ifi.lmu.de>wrote:

> Thanks, Dan and Roman, for the explanation.  So I have to delete the
> explanation "non-recursive let = single-branch case" from my brain.
>
> I thought the guards in a let are assertations, but in fact it is more
> like an if.  Ok.
>
> But then I do not see why the pattern variables are in scope in the guards
> in
>
>   let p | g = e
>
> The variables in p are only bound to their values (given by e) if the
> guard g evaluates to True.  But how can g evaluate if it has yet unbound
> variables?  How can ever a pattern variable of p be *needed* to compute the
> value of the guard?  My conjecture is that it cannot, so it does not make
> sense to consider variables of g bound by p.  Maybe you can cook up some
> counterexample.
>
> I think the pattern variables of p should not be in scope in g, and
> shadowing free variables of g by pattern variables of p should be forbidden.
>
> Cheers,
> Andreas
>
> On 09.07.2013 17:05, Dan Doel wrote:> The definition
>
> >
> >      Just x | x > 0 = Just 1
> >
> > is recursive. It conditionally defines Just x as Just 1 when x > 0 (and
> > as bottom otherwise). So it must know the result before it can test the
> > guard, but it cannot know the result until the guard is tested. Consider
> > an augmented definition:
> >
> >      Just x | x > 0  = Just 1
> >             | x <= 0 = Just 0
> >
> > What is x?
>
> On 09.07.2013 17:49, Roman Cheplyaka wrote:
>
>> As Dan said, this behaviour is correct.
>>
>> The confusing thing here is that in case expressions guards are attached
>> to the patterns (i.e. to the lhs), while in let expressions they are
>> attached to the rhs.
>>
>> So, despite the common "Just x | x > 0" part, your examples mean rather
>> different things.
>>
>> Here's the translation of 'loops' according to the Report:
>>
>>    loops =
>>      let Just x =
>>        case () of
>>          () | x > 0 -> Just 1
>>      in x
>>
>> Here it's obvious that 'x' is used in the rhs of its own definition.
>>
>> Roman
>>
>> * Andreas Abel <andreas.abel at ifi.lmu.de> [2013-07-09 16:42:00+0200]
>>
>>> Hi, is this a known bug or feature of GHC (7.4.1, 7.6.3)?:
>>>
>>> I got a looping behavior in one of my programs and could not explain
>>> why.  When I rewrote an irrefutable let with guards to use a case
>>> instead, the loop disappeared.  Cut-down:
>>>
>>>    works = case Just 1 of { Just x | x > 0 -> x }
>>>
>>>    loops = let Just x | x > 0 = Just 1 in x
>>>
>>> works returns 1, loops loops.  If x is unused on the rhs, the
>>> non-termination disappears.
>>>
>>>    works' = let Just x | x > 0 = Just 1 in 42
>>>
>>> Is this intended by the Haskell semantics or is this a bug?  I would
>>> have assumed that non-recursive let and single-branch case are
>>> interchangeable, but apparently, not...
>>>
>>> Cheers,
>>> Andreas
>>>
>>> --
>>> Andreas Abel  <><      Du bist der geliebte Mensch.
>>>
>>> Theoretical Computer Science, University of Munich
>>> Oettingenstr. 67, D-80538 Munich, GERMANY
>>>
>>> andreas.abel at ifi.lmu.de
>>> http://www2.tcs.ifi.lmu.de/~**abel/ <http://www2.tcs.ifi.lmu.de/~abel/>
>>>
>>> ______________________________**_________________
>>> Haskell-Cafe mailing list
>>> Haskell-Cafe at haskell.org
>>> http://www.haskell.org/**mailman/listinfo/haskell-cafe<http://www.haskell.org/mailman/listinfo/haskell-cafe>
>>>
>>
>>
>
> --
> Andreas Abel  <><      Du bist der geliebte Mensch.
>
> Theoretical Computer Science, University of Munich
> Oettingenstr. 67, D-80538 Munich, GERMANY
>
> andreas.abel at ifi.lmu.de
> http://www2.tcs.ifi.lmu.de/~**abel/ <http://www2.tcs.ifi.lmu.de/~abel/>
>
> ______________________________**_________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/**mailman/listinfo/haskell-cafe<http://www.haskell.org/mailman/listinfo/haskell-cafe>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130709/29727572/attachment.htm>


More information about the Haskell-Cafe mailing list