Haskell "ничего не делать" IO, или если без него

Я хочу что-то сделать в Haskell, который выглядит так:

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

Очевидно, это не является законным, так как нет else. Один из вариантов, о котором я думал:

nop :: IO ()
nop = sequence_ []

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

Это немного подробный, но я бы согласился на это, если это необходимо. Я был бы удивлен, если бы не была встроенная версия nop.

В качестве альтернативы:

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

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

Это более красноречиво, но синтаксис не особенно приятен. Опять же, я не удивлюсь, если найду что-то встроенное, которое уже существует.

Какой предпочтительный способ сделать это?

Ответ 1

Самый простой способ сделать no-op в монаде:

return ()

Однако для конкретной идиомы, которую вы делаете, есть комбинатор, уже сделанный для вас:

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

Этот комбинатор when ведет себя точно так же, как и комбинатор doIf:)

Ответ 2

Вы можете использовать Hoogle для поиска функций, в данном случае: when.

В Hoogle вы можете ввести подпись типа и попытаться найти соответствующие функции в стандартных библиотеках, объединив типы и аргументы переупорядочения.

В вашем случае вы можете просто ввести тип своей функции doIf: Bool → IO() → IO(). when - это третий ответ, здесь также обратный unless.