Pattern guards and where clauses

Ravi Nanavati ravi at
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

More information about the Haskell-prime mailing list