Haskell "нічого не робить" IO, або навіть без іншого


81

Я хочу зробити щось у 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")

Це більш стисло, але синтаксис не особливо приємний. Знову ж таки, я не здивувався б, знайшовши щось вбудоване, що вже існує.

Який найкращий спосіб це зробити?

Відповіді:


116

Найпростіший спосіб зробити відмову в монаді - це:

return ()

Еквівалентно:

pure ()

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

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

Цей whenкомбінатор поводиться точно так само, як ваш doIfкомбінатор :)


1
На жаль, я думав про return (), але думав, що він насправді повернеться (тобто коротке замикання решти речей у виразі do). Моє ліжко. Дякуємо за вказівник на коли.
Дейв Б

7
повернення - це якась погана назва для нього, так :)
bdonlan

9
@Dave Майте на увазі, що returnв Haskell це не мовна конструкція, це просто функція (з неправильно підібраною назвою, як каже bdonian). Повернення не впливає на керуючий потік, або щось інше, ви можете написати: do {s <- getLine; return (); putStrLn s}це буде виконано чудово
Том Локхорст,

Я отримую Not in scope: `when'для test = do (when True (putStrLn "Hello")).
Qwertie,

3
На жаль, whenпотрібно import Control.Monadвгорі файлу.
Qwertie

20

Ви можете використовувати Hoogle знайти функції, в даному випадку: when.

У Hoogle ви можете ввести підпис типу, і він спробує знайти відповідні функції в стандартних бібліотеках, об'єднуючи типи та впорядковуючи аргументи.

У вашому випадку ви можете просто ввести тип своєї doIfфункції: Bool -> IO () -> IO () . whenце третя відповідь тут, unlessтам є і її зворотний бік .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.