Haskell“不执行任何操作” IO,或者如果不执行其他操作


80

我想在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")

这更加简洁,但是语法不是特别好。再次,我不会惊讶地发现已经存在的内置功能。

首选的方法是什么?

Answers:


114

在monad中执行不操作的最简单方法是:

return ()

等效地:

pure ()

但是,对于您正在使用的特定用法,已经有一个组合器供您使用:

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

when组合器的行为与您的doIf组合器完全相同:)


1
糟糕,我想到了return(),但我想它实际上会返回(即,将do-expression中的其余内容短路)。我的错。感谢您指向when的指针。
Dave B

6
return对于它来说是一个坏名字,是的:)
bdonlan

8
@Dave请记住,return在Haskell中,它不是语言构造,而只是一个函数(如bdonian所说,名称选择错误)。Return不会影响控制流,或者您可以编写一些内容:do {s <- getLine; return (); putStrLn s}可以很好地执行。
汤姆·洛赫斯特

Not in scope: `when'test = do (when True (putStrLn "Hello"))
Qwertie 2014年

3
糟糕,when要求import Control.Monad位于文件顶部。
Qwertie

20

在这种情况下,您可以使用Hoogle查找功能when

在Hoogle中,您可以输入类型签名,然后它将通过统一类型和重新排序参数来尝试在标准库中查找匹配的函数。

在您的情况下,您只需输入doIf函数的类型即可:Bool-> IO()-> IO() when是这里的第三个答案,unless也有相反的答案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.