Difference between revisions of "Case"

From HaskellWiki
Jump to: navigation, search
(more flavors)
Line 75: Line 75:
 
Alternatively, one could simply factor out a function(/value) and use guards in the argument patterns.
 
Alternatively, one could simply factor out a function(/value) and use guards in the argument patterns.
   
  +
=== Using list comprehensions ===
  +
  +
An alternative sugarful approach is to use [[list comprehension]]s.
  +
  +
<haskell>
  +
head $
  +
[ ex1 | cond1 ] ++
  +
[ ex2 | cond2 ] ++
  +
[ ex3 | cond3 ] ++
  +
[ exDefault ]
  +
</haskell>
   
 
[[Category:FAQ]]
 
[[Category:FAQ]]

Revision as of 04:36, 29 January 2008

Question

Can I have a case where the alternatives contain expressions?

Answer

There are several approaches to this problem.

Using functions

We can do this 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)]

Unfortunately this function is not in the Prelude.

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. See if-then-else.

Alternatively you can unroll foldr and write

if' cond1 ex1 $
if' cond2 ex2 $
if' cond3 ex3 $
   exDefault

If you use if' in infix form, you may call it ? like in C, then because of partial application it will work nicely together with '$' for the else clause.

infixl 1 ?
(?) :: Bool -> a -> a -> a
(?) = if'

cond1 ? ex1 $
cond2 ? ex2 $
cond3 ? ex3 $
   exDefault


Using syntactic sugar

You can make use of some syntactic sugar 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.

Using list comprehensions

An alternative sugarful approach is to use list comprehensions.

head $
  [ ex1 | cond1 ] ++
  [ ex2 | cond2 ] ++
  [ ex3 | cond3 ] ++
  [ exDefault ]