Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using case for a multi-way if

Today, I found myself typing the following code:

case () of
  _ | x < 15 -> ...
  _ | x < 25 -> ...
  _ | x < 50 -> ...
  _          -> ...

The meaning of this is straight-forward enough, but it just feels... wrong to utter case (). Does anybody have a better suggestion?

I suppose since I'm branding on x, I could have written case x. But that still leaves me with nothing to actually pattern-match on; it's all about the guards. And that still feels weird.

like image 635
MathematicalOrchid Avatar asked Jul 04 '13 20:07

MathematicalOrchid


3 Answers

There is nothing wrong with case (); it is the best you have for this use-case unless you want to use very recent syntactic and non-standard-extensions like GHC’s multi-way-if.

like image 90
Joachim Breitner Avatar answered Oct 21 '22 20:10

Joachim Breitner


Others have mentioned that case if fine and mutli-way if exists, but I'd go for a local function via a where or let statement:

someFunction = do
    x <- monadicOp
    let f y | y < 5  = expr1
            | y < 15 = expr2
            | y < 25 = expr3
            | True   = expr4
    f x

This is syntactically cleaner than the case statement solution and more portable than multi-way if.

EDIT:

In case it isn't clear, if the value being compared, x in this case, is already in scope when you define the guarded function (f) then you could just define a value instead:

someFunction = do
    x <- monadicOp
    let r | x < 15 = expr1
          | x < 25 = expr2
    r
like image 41
Thomas M. DuBuisson Avatar answered Oct 21 '22 19:10

Thomas M. DuBuisson


You can exploit lazy evaluation to come up with something like this:

import Data.List
import Data.Maybe
import Control.Applicative

cases :: [(Bool,a)] -> a -> a
cases lst d = snd $ fromJust $ (find fst lst) <|> Just (True,d)

main = do
  let x = 20
      r = cases [(x < 15, putStr "15"),
                 (x < 25, putStr "25"),
                 (x < 50, putStr "50")] $ putStr "None"
    in
       r
like image 21
Ankur Avatar answered Oct 21 '22 18:10

Ankur