From HaskellWiki
Revision as of 10:41, 16 October 2006 by Lemming (talk | contribs) (one colon too much)

Jump to: navigation, search

Can I have a case where the alternatives contain expressions?

You can make use of some SyntacticSugar of Haskell, namely of Guards.

case () of _
             | cond1     -> ex1
             | cond2     -> ex2
             | cond3     -> ex3
             | otherwise -> exDefault

Alternatively, one could simply factor out a function(/value) and use guards in the argument patterns.

Why sticking to syntactic sugar? We can do it nicely with a function implemented in Haskell:

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

select exDefault
    [(cond1, ex1),
     (cond2, ex2),
     (cond3, ex3)]

Alternative implementations are

select' def = fromMaybe def . lookup True

{- a purely functional implementation of if-then-else -}
if' :: Bool -> a -> a -> a
if' True  x _ = x
if' False _ y = y

select'' = foldr (uncurry if')

The implementation of select'' makes clear that select can be considered as nested ifs. The functional if' is also useful in connection with zipWith3 since zipWith3 if' merges two lists according to a list of conditions.

If you don't like the parentheses for the pairs, you can also define

data SelectBranch a = (:->) {
  condition  :: Bool,
  expression :: a

select :: a -> [SelectBranch a] -> a
select def = maybe def expression . List.find condition

select exDefault
    [cond1 :-> ex1,
     cond2 :-> ex2,
     cond3 :-> ex3]