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

Andreas Abel andreas.abel at ifi.lmu.de
Tue Jul 9 19:12:29 CEST 2013

```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/
>>
>> _______________________________________________
>

--
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/

```