Pattern guards

Conor McBride ctm at
Thu Sep 28 14:30:46 EDT 2006


Yitzchak Gale wrote:
> I would like to suggest a correction to ticket #56,
> "Pattern Guards".
> It is easy to show that every expression written
> using pattern guards can also be written in
> Haskell 98 in a way that is essentially
> equivalent in simplicity. (Proof below.)

Whether or not your conclusion is correct, your candidate proof is 

> funlhs
> | qual11, qual12, ..., qual1n = exp1
> | qual21, qual22, ..., qual2n = exp2
> ...
> we translate the function binding into Haskell 98 as:
> funlhs = runExit $ do
>  maybeExit $ do {qual11'; qual12'; ...; qual1n'; return (exp1)}
>  maybeExit $ do {qual21'; qual22'; ...; qual2n'; return (exp2)}
>  ...

This translation does not appear to address programs with multiple 
left-hand sides, exploiting fall-through from match (hence guard) 
failure, eg

  varVal :: String -> [(String, String)] -> String
  varVal x locals | Just y <- lookup x locals = y
  varVal "X" xys = "42"
  varVal _ _ = error "var not found"

Haskell 98 provides no means to inspect the value of an intermediate 
computation (something other than an argument or component thereof) 
without committing to one right-hand side. I think that's rather 
unfortunate, because it loses the visual tabulation of the possibilities 
and priorities.

I'm not a big fan of pattern guards, though, because they only give you 
one shot at matching the intermediate result. Some means to do 'case e' 
on the left would be nice. Maybe

  gcd x y | compare x y ->
    LT = gcd x (y - x)
    GT = gcd (x - y) y
  gcd x _ = x

or some such. I wish I could think of a better example without too much 
context, but such a thing escapes me for the moment. In general, I think 
it's good to collocate on the left as much as possible of a function's 
scrutineering. Stringing out ifs and cases makes it harder to see what's 
going on.

All the best


More information about the Haskell-prime mailing list