Pattern guards and where clauses

Ravi Nanavati ravi at bluespec.com
Sun Nov 19 20:46:41 EST 2006

```While playing with some pattern guard code, I discovered some scoping
behavior that I wasn't expecting. I learned that pattern guard bindings
aren't visible in their equation's where clauses. To make this concrete,
in the following (contrived) example, "test1" works, but "test2"
complains that 'v' is unbound:

data Bar = Baz Int | Biz Int | Empty

toInt (Baz i) = Just i
toInt (Biz i) = Just (2 * i)
toInt Empty   = Nothing

test1 :: Bar -> Int
test1 b | Just v <- toInt b = v + 1
test1 _ = 0

test2 :: Bar -> Int
test2 b | Just v <- toInt b = k
where k = v + 1
test2 _ = 0

From an implementation perspective, I understand the behavior as an
artifact of desugaring pattern guards into a case expression. But, as a
user, it seems like an odd restriction on how I organize my code (since
I often prefer to separate out tricky bits of logic into nearby where
clauses without disturbing the main flow of the right-hand side).

Moreover, unless I'm missing something, a slight tweak to the desugaring
(by adding irrefutable patterns corresponding to the pattern guard
bindings) could easily recover the behavior I expected.

I'm thinking something like this (which could be tweaked to remove the
repeated expression, of course):

test2' :: Bar -> Int
test2' b | Just v <- toInt b = k
where Just v = toInt b
k = v + 1

Anyway, what do other people think? Do people besides me find it
pleasing to have pattern guard bindings visible in where clauses? Or are
people more worried about the failures that would happen if you used a
binding from a pattern guard that ended up false?

- Ravi
```