Pattern guards

David Roundy droundy at darcs.net
Sat Sep 30 23:04:12 EDT 2006


On Sun, Oct 01, 2006 at 02:08:35AM +0200, Yitzchak Gale wrote:
> David Roundy wrote:
> >>foo (Left "bar") = "a"
> >>foo (Right x) | (b,"foo") <- break (==' ') x = "b " ++ b
> >>              | ["Hello",n,"how","are","you",d@(_:_)] <- words x,
> >>                last d == '?'
> >>        = n ++ " is not here right now, but " ++ n ++ " is " ++
> >>          init d ++ " fine."
> >>foo (Left x) | ("foo",c) <- break (==' ') x = "c " ++ c
> >>             | length x == 13 = "Unlucky!"
> >>foo (Right x) = x
> >>foo (Left x) = x
> 
> And here it is in Haskell 98:
> 
> >foo (Left "bar") = "a"
> >foo (Right x) | isExit y = runExit y
> > where y = do
> >  maybeExit $ do (b,"foo") <- return $ break (==' ') x
> >                 return $ "b" ++ b
> >  maybeExit $ do ["Hello",n,"how","are","you",d@(_:_)] <- return $ words x
> >                 guard $ last d == '?'
> >                 return $ n ++ " is not here right now, but " ++
> >                          n ++ " is " ++ init d ++ " fine."
> >foo (Left x) | isExit y = runExit y
> > where y = do
> >  maybeExit $ do ("foo",c) <- break (==' ') x
> >                 return $ "c" ++ c
> >  when (length x == 13) $ Exit "Unlucky!"
> >foo (Right x) = x
> >foo (Left x) = x

I disagree as far as the beauty of this approach.  You require that
every pattern guard involves a where binding, plus the use of a three
function calls (isExit, runExit and maybeExit, plus sometimes one or
more calls to guard).  In my opinion that makes it less concise than
the usual pattern matching approach.

One extra where binding may not much matter in simple functions like
this, but in complicated functions that are already hard to read and
understand (because they do complicated things, not because they're
poorly written), throwing in extra where bindings is just a waste.

Also, in your code you're forced to mingle the "pattern matching" with
the actual code itself, which to me makes the result less legible.
And would be even worse if the function were one that returns a
monadic result, so the reader would be forced to distinguish between
the do in the Exit monad and the do in the output monad.

Pattern guards feel very natural, are very easy to read, and won't
bother you if you don't use them.  As you point, they're just
syntactic sugar, and therefore are "safe", in that they can't lead to
any weird or confusing semantics.
-- 
David Roundy


More information about the Haskell-prime mailing list