logo       

Re: Guards (Was: Some random newbie questions): msg#00114

lang.haskell.cafe

Subject: Re: Guards (Was: Some random newbie questions)

Jon Cast wrote:

Absolutely. In Haskell's syntax, if-then-else-if interacts badly with
do notation, and Haskell lacks a direct analogy to Lisp's cond.

case () of
() | p1 -> e1
| p2 -> e2
...

No problem:

select :: a -> [(Bool, a)] -> a
select def = maybe def snd . List.find fst

Use it this way:

select defaultE
[(p1, e1),
(p2, e2)]

Would be a nice Prelude function.

parseCmd ln
| Left err <- parse cmd "Commands" ln
= BadCmd $ unwords $ lines $ show err
| Right x <- parse cmd "Commands" ln
= x

with the Haskell-98 alternative

parseCmd ln = case parse cmd "Commands" ln of
Left err -> BadCmd $ unwords $ lines $ show err
Right x -> x

Really, the second alternative is cleaner in my opinion.

Furthermore, guards are an extension of pattern matching, which means
you can write code like this:

xn !! n | n < 0 = error "Prelude.(!!): Negative index"
[] !! n = error "Prelude.(!!): Index overflow"
(x:xn) !! n | n == 0 = x
(x:xn) !! n = xn !! (n - 1)

Exactly one equation for each edge in the control-flow graph, which is
nice and not easily done (I'm not sure it's even possible) without
guards.

At least one guard can nicely be avoided:

(x:xn) !! n = if n == 0 then x else xn !! (n - 1)

But I see that guards can be used to let pattern matching fail.


Pattern guards are also nice for implementing ‘views’:

-- | Convert an 'XMLData' into an equivalent application of
-- 'Balanced', if possible. In any case, return an equivalent data
-- structure.
balance (Balanced es) = Balanced es
balance (LeftLeaning (LeftBalanced e:es))
| Balanced es' <- balance (LeftLeaning es)
= Balanced (e:es')

I don't know what this means exactly, but I think I can transform it formally to:

balance e'@(LeftLeaning (LeftBalanced e:es)) =
case balance (LeftLeaning es) of
Balanced es' -> Balanced (e:es')
_ -> e'

This way it is more clear for me, that 'balance' can return something different from 'Balanced' and that the data is returned unchanged in this case.

balance (LeftLeaning []) = Balanced []
balance (RightLeaning [("", "", es)]) = Balanced es
balance (RightLeaning []) = Balanced []
balance e = e


Well, I could never do without them.

Sometimes I see people abusing guards, e.g. they write a 'length x == 1' guard, where the pattern '[x0]' would be clearly the better choice. So I'm always thinking twice before using a guard.


<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise