管理IO monad

Pau*_*han 5 haskell

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

这个例程出错了.我对do&< - 语法的理解是它们从monad中提取非Monad类型.所以理解是有缺陷的:这里的正确理解是什么?

exister :: String -> Bool
exister path = do
  fileexist <- doesFileExist path 
  direxist <- doesDirectoryExist path
  return fileexist || direxist 
Run Code Online (Sandbox Code Playgroud)

错误

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 }
Run Code Online (Sandbox Code Playgroud)

Jos*_*Lee 11

第一个问题:该行return fileexist || direxist被解析为(return fileexist) || direxist,并且您不能m Bool作为第一个参数传递||.将其更改为return (fileexist || direxist).

第二个问题:你声称返回类型existerBool,但编译器推断它必须是IO Bool.修理它.(do<-语法允许您am a值中提取值,但前提是您保证返回m a值.)

  • @Paul您的计算可以是纯粹的,但您的操作显然是IO.例如,IO monad中的`main`例程可以从磁盘或网络获取数据(例如:`x < - getData`)并将该数据传递给纯计算(例如:`let result = computationOn x`)然后发送结果(`sendOnNetwork result`). (9认同)
  • @Paul:那是不可能的.文件/目录是否存在取决于环境.这是一个不纯的功能,因此它必须返回`IO Bool`.在相同输入的情况下,纯函数必须始终返回相同的输出.这显然不是这里的情况. (7认同)

acf*_*zer 5

你给出的类型exister :: String -> Bool是一个返回普通非monadic的函数Bool.您正在执行的操作,doesFileExist path并且doesDirectoryExist path具有类型IO Bool,因此m Bool错误消息中的确实意味着IO Bool.如果更改exister要返回IO Bool的类型,则类型将是您想要的类型.

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