【问题标题】:In Haskell, is there a way to do IO in a function guard?在 Haskell 中,有没有办法在函数保护中进行 IO?
【发布时间】:2011-01-09 11:26:25
【问题描述】:

例如:

newfile :: FilePath -> IO Bool
newfile x | length x <= 0 = return False
          | doesFileExist x == True = return False
          | otherwise = return True

这可以实现吗?

【问题讨论】:

标签: haskell io guard


【解决方案1】:

你已经在 IO monad 中了,为什么不使用下面的呢?

newfile :: FilePath -> IO Bool
newfile x | length x <= 0 = return False
          | otherwise = do exists <- doesFileExist x
                           return $ not exists

为了应用的好处:

import Control.Applicative

newfile :: FilePath -> IO Bool
newfile x | length x <= 0 = return False
          | otherwise = not <$> doesFileExist x

如您所见,applicative route 比您想在问题中使用的守卫更简洁!

【讨论】:

    【解决方案2】:

    不,没有办法做到这一点(缺少不安全的技巧,在这里完全不合适)。

    顺便说一句,如果可能的话,doesFileExist x == True 最好写成doesFileExist x

    【讨论】:

      【解决方案3】:

      这可以工作并且可以满足需要:

      newfile :: FilePath -> IO Bool
      newfile fn = do 
          x <- runErrorT $ do
              when ((length fn) <= 0) (throwError "Empty filename")
              dfe <- liftIO $ doesFileExist fn
              when (dfe) (throwError "File already exists")
              return True
          return $ either (\_ -> False) id x
      

      【讨论】:

      • \\_ -&gt; False 可以写成const False。从风格上讲,我认为后者更能表达意图,但实际上是等效的。
      【解决方案4】:

      保护子句的类型必须是BooldoesFileExist x 的类型是 IO Bool。类型不匹配意味着你不能这样做。

      【讨论】:

      • 这并不意味着什么。 getLine 的类型是 IO String(++ "foo") 的类型是 String -&gt; String。但是您仍然可以使用正确的组合符将getLine 输入(++ "foo")。 (即(++ "foo") &lt;$&gt; getLine 而不是(++ "foo") $ getLine。所以这个问题的答案并不像你的帖子可能让别人相信的那么简单。(我认为“不”这个词实际上比你的帖子更正确。)
      • 我不确定我是否理解你的意思。我不确定您希望如何使用组合器从IO Bool 中获得Bool。虽然您可以使用unsafePerformIOIO Bool 中获取Bool,但请不要。除此之外,保护子句需要Bool 表达式,而不是任何其他类型的表达式。那么我错过了什么?单个词“否”如何更正确,而不是解释什么是预期类型和给定类型是什么?
      • @jrockway yfeldblum 是正确的。 IO 的全部是没有办法将IO a 变成a。使用正确的组合器将(++ "foo") 应用到getLine 不会将getLine 拉出IO 使其成为String,以便它适合(++ "foo") 的类型,它会将(++ "foo") 进入 IO 使其适合getLine 的类型。没有办法在您期望能够使用String 的地方使用(++ "foo") &lt;$&gt; getLine,这是设计使然。在需要Bool 的地方也无法使用IO Bool 的值。
      猜你喜欢
      • 2015-01-27
      • 1970-01-01
      • 2021-04-19
      • 1970-01-01
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多