15

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

所以目前我有

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,这将是不安全的,对吗?(<-)根本就不是一个函数吗?

4

3 回答 3

17

如果适合您的目的,您可以使用ifMfrom Control.Conditional,并且编写类似的功能甚至不难。

只是给你举个例子

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 e2类似的语法,ifM但不值得尝试这样做。

于 2013-06-06T02:02:40.980 回答
6

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

{-# LANGUAGE LambdaCase #-}

导入 System.Directory

主要=做
    dosFileExist "/etc/passwd" >>= \case
        真 -> putStrLn “是”
        假-> putStrLn“否”

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

于 2013-06-06T19:05:00.913 回答
1

你不能。好吧,老实说,有一个“hack”可以让你至少编写这样的代码并让它编译,但结果几乎肯定不会是你想要或期望的。

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

于 2013-06-06T01:52:33.857 回答