将配置文件读入 Haskell 时发生 IO

use*_*428 0 io monads haskell file-read do-notation

我有用于我尚未编写的 Haskell 应用程序的输入数据,这些数据驻留在一个文件中。我不更新文件。我只需要读取文件并将其输入到需要字符串列表的 Haskell 函数中。但是读取文件当然会产生IO数据对象。我了解到使用该<-操作可以以某种方式“取出”打包在IO结构中的字符串,因此我尝试了以下尝试:

run :: [String]
run = do
  datadef_content <- readFile "play.txt" -- yields a String
  let datadef = lines datadef_content -- should be a [String]
  return datadef
Run Code Online (Sandbox Code Playgroud)

我把它放到一个文件中play.hs,然后从 ghci 加载它

:l play
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,我收到了该readFile行的错误消息

 Couldn't match type ‘IO’ with ‘[]’
 Expected type: [String]
   Actual type: IO String
Run Code Online (Sandbox Code Playgroud)

return错误信息

 Couldn't match type ‘[Char]’ with ‘Char’
 Expected type: [String]
   Actual type: [[String]]
Run Code Online (Sandbox Code Playgroud)

第一条似乎表明我无法摆脱IO,而最后一条消息似乎表明,这lines将返回一个字符串列表列表,这对我来说也没有意义。

我怎样才能正确地做到这一点?

che*_*ner 5

您声明run为一个[String]值。但return不是提供函数返回值的关键字;它一个函数,类型为Monad m => a -> m areturn datadef产生一个 type 的值IO [String],它成为函数的返回值。

解决方案是为 提供正确的返回类型run

run :: IO [String]
run = do
    ...
Run Code Online (Sandbox Code Playgroud)

run 也可以更简洁地定义为

run = fmap lines (readFile "play.txt")
Run Code Online (Sandbox Code Playgroud)

虽然do语法建议是,没有办法拉值一个的IO动作; 您所能做的就是将调用“推送”lines 操作中。