关于IO的困惑和做法

时间:2014-01-26 16:43:15

标签: haskell io monads

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

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

但它给了我这个错误:

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) }

parseLogLine的类型签名为parseLogLine :: B8.ByteString -> Either String Record

我完全惊讶。 B.readFile path应该返回IO ByteString,因此f应该是ByteStringC8.lines f应该返回[ByteString],地图应该return [Either String Record]

我哪里错了?

1 个答案:

答案 0 :(得分:7)

作为起点,readRecords的定义类型错误。如果do块在IO monad中工作,那么它将生成IO值,但您已将其定义为返回[Either String Record] [] {1}} monad。这意味着您无法在不触发类型错误的情况下调用返回B.readFile的{​​{1}}。

修复后,您会发现do块最后一行的IO表达式类型错误,因为它生成map时会生成[Either String Record]。在IO [Either String Record]中换取呼叫以解决此问题。