【问题标题】:Managing the IO monad管理 IO 单子
【发布时间】:2011-10-17 18:21:10
【问题描述】:

我正在学习一些 Haskell(请原谅新手错误)-

此例程出错。我对 do &

exister :: String -> Bool
exister path = do
  fileexist <- doesFileExist path 
  direxist <- doesDirectoryExist path
  return fileexist || direxist 

错误

ghc -o joiner joiner.hs

joiner.hs:53:2:
    Couldn't match expected type `Bool' against inferred type `m Bool'
    In the first argument of `(||)', namely `return fileexist'
    In the expression: return fileexist || direxist
    In the expression:
        do { fileexist <- doesFileExist path;
             direxist <- doesDirectoryExist path;
               return fileexist || direxist }

【问题讨论】:

  • 从您下面的评论来看,您可能想查看这个问题及其答案:stackoverflow.com/questions/6628748/…(我们确实需要一个适当的常见问题解答)
  • 我认为指出 Haskell 的 return 与大多数语言中的“return”不太相似,这可能会有所帮助。如果您想要一个接受数字 n 并“返回”n+1 的函数,请编写 f n = n + 1,而不是 f n = return n+1

标签: haskell


【解决方案1】:

您给exister :: String -&gt; Bool 的类型用于返回普通的非单子Bool 的函数。您正在执行的操作,doesFileExist pathdoesDirectoryExist path 具有 IO Bool 类型,因此错误消息中的 m Bool 真正意味着 IO Bool。如果您将exister 的类型更改为返回IO Bool,则该类型将是您想要的。

另外,在最后一行,你需要更多的括号:return (fileexist || direxist)

【讨论】:

    【解决方案2】:

    第一个问题:return fileexist || direxist 被解析为(return fileexist) || direxist,你不能将m Bool 作为|| 的第一个参数传递。将其更改为return (fileexist || direxist)

    第二个问题:你声称exister的返回类型是Bool,但是编译器推断它一定是IO Bool。修理它。 (do&lt;- 语法允许您从 m a 值中提取 a 值,但前提是您承诺返回 m a 值。)

    【讨论】:

    • 我向你保证,我希望exister 返回一个Bool,而不是IO Bool。
    • @Paul:这是不可能的。文件/目录是否存在,取决于环境。它是一个不纯函数,因此它必须返回IO Bool。给定相同的输入,纯函数必须始终返回相同的输出。这显然不是这里的情况。
    • @hammar:所以如果我的整个程序都是围绕从硬盘/网络中吸取数据、处理数据并将其发送出去,那么我在所有计算中都必须使用 IO monad?
    • @Paul 您的计算可以是纯的,但您的操作显然是 IO。例如,位于 IO monad 中的 main 例程可以从磁盘或网络获取数据(例如:x &lt;- getData)并将该数据传递给纯计算(例如:let result = computationOn x)然后将结果发送出去(@ 987654338@).
    • @Paul Nathan,我在开始时遇到了您的确切问题。幸运的是,学习曲线值得付出努力。
    猜你喜欢
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 2013-11-09
    相关资源
    最近更新 更多