关于IO的困惑和做法

utd*_*mir 1 io monads haskell

我是Haskell的初学者,对我编写的这段代码感到困惑

readRecords :: String -> [Either String Record]
readRecords path = do
    f <- B.readFile path
    map parseLogLine (C8.lines f)
Run Code Online (Sandbox Code Playgroud)

但它给了我这个错误:

Main.hs:15:10:
    Couldn't match type `IO' with `[]'
    Expected type: [C8.ByteString]
      Actual type: IO C8.ByteString
    In the return type of a call of `B.readFile'
    In a stmt of a 'do' block: f <- B.readFile path
    In the expression:
      do { f <- B.readFile path;
           map parseLogLine (C8.lines f) }
Run Code Online (Sandbox Code Playgroud)

parseLogLine的签名是parseLogLine :: B8.ByteString -> Either String Record.

我完全惊讶.B.readFile path应该返回IO ByteString,所以f应该ByteString.C8.lines f应该返回[ByteString]并映射return [Either String Record].

我哪里错了?

GS *_*ica 7

作为起点,readRecords用错误的类型定义.如果do块是在工作IO单子,那么它就会产生IO价值,但你把它定义为恢复[Either String Record]这是在[]单子.这意味着你不能B.readFileIO不触发你得到的类型错误的情况下调用哪个返回.

一旦你解决了这个问题,你会发现mapdo块的最后一行上的表达式有错误的类型,因为它产生的[Either String Record]时候会生成IO [Either String Record].将呼叫包裹起来return以解决此问题.