有没有办法在if语句中使用IO Bool而不绑定haskell中的名称?

时间:2013-06-06 01:25:23

标签: haskell monads

如果我有一个返回IO Bool的函数(特别是atomically),有没有办法直接在if语句中使用返回值,而不绑定?< / p>

所以目前我已经

ok <- atomically $ do
  ...
if (ok) then do
  ...
else do
  ...

是否可以将其写为

之类的内容
if (*some_operator_here* atomically $ do
      ...) then do
  ...
else do
  ...

我希望有一种方法可以匿名使用<-之类的东西,即if (<- atomically ...),但到目前为止还没有这样的运气。

同样在getLine上,是否可以编写类似

的内容
if ((*operator* getLine) == "1234") then do ...

相关附录 - (<-)的类型是什么?我无法让它出现在ghci中。我假设它是m a -> a,但那意味着它可以在monad之外使用来逃避那个不安全的monad,对吧? (<-)根本不是一个功能吗?

3 个答案:

答案 0 :(得分:16)

如果符合您的目的,您可以使用Control.Conditional中的ifM,甚至难以编写类似的功能。

只是举个例子

import Control.Conditional
import Control.Monad

(==:) :: ( Eq a,Monad m) => m a -> m a -> m Bool
(==:) = liftM2 (==)

main = ifM (getLine ==: getLine) (print "hit") (print "miss")

我认为有一些方法可以使用可重新绑定的语法扩展,你甚至可以使用if c then e1 else e2ifM的语法,但是不值得努力尝试。

答案 1 :(得分:4)

使用GHC 7.6和LambdaCase语言扩展,您可以编写

{-# LANGUAGE LambdaCase #-}

import System.Directory

main = do
    doesFileExist "/etc/passwd" >>= \case
        True ->  putStrLn "Yes"
        False -> putStrLn "No"

它不完全是if..then..else,但更接近,不需要绑定到结果,而且有些人(不是我)说H if..then..else在Haskell中是不好的风格。

答案 2 :(得分:1)

不,你不能。嗯,说实话,有一个'hack'允许你至少编写这样的代码并让它编译,但结果几乎肯定不是你想要的或期望的。

为什么这不可能?嗯,首先,类型IO Bool的值在任何意义上都不包含类型Bool的值。相反,它是一个“动作”,执行时将返回类型Bool的值。另一方面,如果这是可能的,它将允许你隐藏在看似纯粹的代码的副作用。这将违反Haskell的核心原则。 Haskell非常有原则。