# Difference between revisions of "Case"

(select in utility-ht) |
(subsections) |
||

Line 8: | Line 8: | ||

=== Using functions === |
=== Using functions === |
||

+ | |||

+ | ==== select ==== |
||

We can do this nicely with a function implemented in Haskell: |
We can do this nicely with a function implemented in Haskell: |
||

Line 22: | Line 24: | ||

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

It is however in the [http://hackage.haskell.org/packages/archive/utility-ht/0.0.1/doc/html/Data-Bool-HT.html#v%3Aselect utility-ht] package. |
It is however in the [http://hackage.haskell.org/packages/archive/utility-ht/0.0.1/doc/html/Data-Bool-HT.html#v%3Aselect utility-ht] package. |
||

+ | |||

+ | ==== nested 'if' ==== |
||

Alternative implementations are |
Alternative implementations are |
||

Line 45: | Line 49: | ||

exDefault |
exDefault |
||

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

+ | |||

+ | ==== infix operator ==== |
||

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

## Revision as of 10:26, 8 January 2009

## Contents

## Question

Can I have a `case`

where the alternatives contain expressions?

## Answer

There are several approaches to this problem.

### Using functions

#### 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.

#### nested 'if'

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 `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
```

#### 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
```

### Using syntactic sugar

#### 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.

#### List comprehensions

An alternative sugarful approach is to use list comprehensions.

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