Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling nested if-else-then in do blocks in Haskell

Tags:

haskell

I've found that I don't know how to handle nested if-else-then in do-blocks in Haskell.

I know already that I can use a case, but that would require all my conditions (a, b and c) to return the same type (Bool, so there are only two cases, but I need three distinct ones) and is therefore not as general (correct me if I'm wrong). I have also tried considering using guards here, but I don't know how to make this work in a do statement, especially if the -- something expressions are meant to be of type IO ().

Suppose I have the following code that is inside a do:

if a then
     -- something
else 
    if b then
        -- something
    else
        if c then
            -- something
        else
            -- something

How do I create the equivalent logic but without all the indenting?

like image 622
MonkeySeeMonkeyCode Avatar asked Dec 23 '22 23:12

MonkeySeeMonkeyCode


1 Answers

To begin with, it is worth noting that if-expressions do not actually require extra indentation (if-within-do used to be an exception, but Haskell 2010 eliminated that). That means you might collapse all the extra indentation:

test = do
    len <- length <$> getLine
    if len < 4
    then putStrLn "Short"
    else if len > 6
    then putStrLn "Long"
    else putStrLn "Mid"

Personally, though, I don't find that too pleasing aesthetically, as I feel some indentation makes if-expressions easier to follow. A nice alternative is using the MultiWayIf extension:

{-# LANGUAGE MultiWayIf #-}

test = do
    len <- length <$> getLine
    if | len < 4 -> putStrLn "Short"
       | len > 6 -> putStrLn "Long"
       | otherwise -> putStrLn "Mid"

On a final note, nested if-expressions getting unwieldy might reveal a good occasion for breaking things down in separate definitions, or otherwise reorganising your code. See also: How do I deal with many levels of indentation?

like image 126
duplode Avatar answered Jan 21 '23 16:01

duplode