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

−  You can make use of some [[syntactic sugar]] of Haskell, namely of [[guard]]s. 
+  There are several approaches to this problem. 
−  <haskell> 
+  === Using functions === 
−  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. 
+  We can do this nicely with a function implemented in Haskell: 
−  
−  Why sticking to syntactic sugar? We can do it nicely with a function implemented in Haskell: 

<haskell> 
<haskell> 

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

Line 17:  Line 20:  
(cond3, ex3)] 
(cond3, ex3)] 

</haskell> 
</haskell> 

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

Alternative implementations are 
Alternative implementations are 

Line 31:  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 [[ifthenelse]]. 

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

−  If you don't like the parentheses for the pairs, you can also define 

<haskell> 
<haskell> 

−  data SelectBranch a = (:>) { 
+  if' cond1 ex1 $ 
−  condition :: Bool, 
+  if' cond2 ex2 $ 
−  expression :: a 
+  if' cond3 ex3 $ 
−  } 
+  exDefault 
−  
−  select :: a > [SelectBranch a] > a 

−  select def = maybe def expression . List.find condition 

−  
−  
−  select exDefault 

−  [cond1 :> ex1, 

−  cond2 :> ex2, 

−  cond3 :> ex3] 

</haskell> 
</haskell> 

−  It is also possible to define a ternary operator '?' like in C. 
+  If you use <hask>if'</hask> in infix form, 
−  Because of partial application it will work nicely together with 
+  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 

−  True ? v = const v 
+  (?) = if' 
−  False ? _ = id 

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 ifthenelse } 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 ifthenelse.
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.