Personal tools

Case

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
(subsections)
(nested 'if': using maybe instead of fromMaybe (no import stmt required))
Line 30: Line 30:
 
<haskell>
 
<haskell>
 
select' def = fromMaybe def . lookup True
 
select' def = fromMaybe def . lookup True
  +
select'b def = maybe def id . lookup True
   
 
{- a purely functional implementation of if-then-else -}
 
{- a purely functional implementation of if-then-else -}

Revision as of 18:25, 15 March 2012

Contents

1 Question

Can I have a
case
where the alternatives contain expressions?

2 Answer

There are several approaches to this problem.

2.1 Using functions

2.1.1 select

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. It is however in the utility-ht package.

2.1.2 nested 'if'

Alternative implementations are

select' def = fromMaybe def . lookup True
select'b def = maybe def id . 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
if
s. 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

2.1.3 infix operator

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


2.2 Using syntactic sugar

2.2.1 Guards

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.

2.2.2 List comprehensions

An alternative sugarful approach is to use list comprehensions.

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