Personal tools

Case

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
m
Line 60: Line 60:
 
It is also possible to define a ternary operator '?' like in C.
 
It is also possible to define a ternary operator '?' like in C.
 
Because of partial application it will work nicely together with
 
Because of partial application it will work nicely together with
'$' for the else cause.
+
'$' for the else clause.
   
 
<haskell>
 
<haskell>

Revision as of 15:25, 13 March 2007

Can I have a
case
where the alternatives contain expressions?


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.

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
if
s. 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]

It is also possible to define a ternary operator '?' like in C. Because of partial application it will work nicely together with '$' for the else clause.

infixl 1 ?
(?) :: Bool -> a -> a -> a
True  ? v = const v
False ? _ = id
 
cond1 ? ex1 $
cond2 ? ex2 $
cond3 ? ex3 $ exDefault