Haskell "do nothing" IO, or if without else

Dave B picture Dave B · May 7, 2009 · Viewed 36.2k times · Source

I want to do something in Haskell that looks like this:

main1 = do s <- getLine
           if s == "foo" then putStr "You entered foo"

Obviously this isn't legal since there's no else. One alternative I've thought of:

nop :: IO ()
nop = sequence_ []

main2 = do s <- getLine
           if s == "foo" then putStr "You entered foo" else nop

This is a little verbose, but I would settle for it if necessary. I would be surprised if there weren't a built-in version of nop, though.

Alternatively:

doIf :: Bool -> IO () -> IO ()
doIf b m = if b then m else nop

main3 = do s <- getLine
           doIf (s == "foo") (putStr "You entered foo")

This is more concise, but the syntax is not particularly nice. Again, I wouldn't be surprised to find something built-in that already exists.

What's the preferred way to do this?

Answer

bdonlan picture bdonlan · May 7, 2009

The easiest way to do a no-op in a monad is:

return ()

Equivalently:

pure ()

However, for the particular idiom you're doing, there's a combinator already made for you:

import Control.Monad
main = do s <- getLine
          when (s == "foo") $ putStr "You entered foo"

This when combinator behaves exactly like your doIf combinator :)