# Case

### From HaskellWiki

(Difference between revisions)

m |
(more flavors) |
||

Line 1: | Line 1: | ||

+ | == Question == | ||

+ | |||

Can I have a <hask>case</hask> where the alternatives contain expressions? | Can I have a <hask>case</hask> 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: | |

− | + | ||

− | + | ||

<haskell> | <haskell> | ||

select :: a -> [(Bool, a)] -> a | select :: a -> [(Bool, a)] -> a | ||

Line 25: | Line 20: | ||

(cond3, ex3)] | (cond3, ex3)] | ||

</haskell> | </haskell> | ||

+ | Unfortunately this function is not in the [[Prelude]]. | ||

Alternative implementations are | Alternative implementations are | ||

Line 39: | Line 35: | ||

The implementation of <hask>select''</hask> makes clear that <hask>select</hask> can be considered as nested <hask>if</hask>s. | The implementation of <hask>select''</hask> makes clear that <hask>select</hask> can be considered as nested <hask>if</hask>s. | ||

The functional <hask>if'</hask> is also useful in connection with <hask>zipWith3</hask> since <hask>zipWith3 if'</hask> merges two lists according to a list of conditions. | The functional <hask>if'</hask> is also useful in connection with <hask>zipWith3</hask> since <hask>zipWith3 if'</hask> merges two lists according to a list of conditions. | ||

+ | See [[if-then-else]]. | ||

− | + | Alternatively you can unroll <hask>foldr</hask> and write | |

− | + | ||

<haskell> | <haskell> | ||

− | + | if' cond1 ex1 $ | |

− | + | if' cond2 ex2 $ | |

− | + | if' cond3 ex3 $ | |

− | + | exDefault | |

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

</haskell> | </haskell> | ||

− | + | If you use <hask>if'</hask> in infix form, | |

− | + | you may call it <hask>?</hask> like in C, | |

− | '$' for the else clause. | + | then because of partial application it will work nicely together with '$' for the else clause. |

− | + | ||

<haskell> | <haskell> | ||

infixl 1 ? | infixl 1 ? | ||

(?) :: Bool -> a -> a -> a | (?) :: Bool -> a -> a -> a | ||

− | + | (?) = if' | |

− | + | ||

cond1 ? ex1 $ | cond1 ? ex1 $ | ||

cond2 ? ex2 $ | cond2 ? ex2 $ | ||

− | cond3 ? ex3 $ exDefault | + | cond3 ? ex3 $ |

+ | exDefault | ||

</haskell> | </haskell> | ||

+ | |||

+ | |||

+ | === Using syntactic sugar === | ||

+ | |||

+ | You can make use of some [[syntactic sugar]] of Haskell, namely of [[guard]]s. | ||

+ | |||

+ | <haskell> | ||

+ | case () of _ | ||

+ | | cond1 -> ex1 | ||

+ | | cond2 -> ex2 | ||

+ | | cond3 -> ex3 | ||

+ | | otherwise -> exDefault | ||

+ | </haskell> | ||

+ | |||

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

+ | |||

+ | |||

+ | [[Category:FAQ]] | ||

[[Category:Idioms]] | [[Category:Idioms]] |

## Revision as of 13:29, 31 May 2007

## Contents |

## 1 Question

Can I have acase

## 2 Answer

There are several approaches to this problem.

### 2.1 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')

select''

select

if

if'

zipWith3

zipWith3 if'

See if-then-else.

Alternatively you can unrollfoldr

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

if'

?

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

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.