Pattern guards and where clauses

Simon Peyton-Jones simonpj at microsoft.com
Mon Nov 20 04:14:07 EST 2006


|  From an implementation perspective, I understand the behavior as an
| artifact of desugaring pattern guards into a case expression. But, as a

It's definitely not an artefact of the implementation; it's just a consequence of Haskell's design.

'where' clauses scope over multiple guards, and must do so

        f x | wibble > 0 = rhs1
            | wibble < 0  = rhs2
             | otherwise  = rhs3
           where
                wibble = sqrt x + 77

Remember you can use 'let' in pattern guards

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

Simon

| -----Original Message-----
| From: haskell-prime-bounces at haskell.org [mailto:haskell-prime-bounces at haskell.org] On Behalf Of
| Ravi Nanavati
| Sent: 20 November 2006 01:47
| To: haskell-prime at haskell.org
| Subject: Pattern guards and where clauses
|
| 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
| _______________________________________________
| Haskell-prime mailing list
| Haskell-prime at haskell.org
| http://www.haskell.org/mailman/listinfo/haskell-prime


More information about the Haskell-prime mailing list