【发布时间】:2020-05-18 14:53:59
【问题描述】:
我已经为我尚未编写的 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
我把它放到一个文件 play.hs 中,然后通过 ghci 加载它
:l play
令我惊讶的是,我收到了readFile 行的错误消息
Couldn't match type ‘IO’ with ‘[]’ Expected type: [String] Actual type: IO String
对于return 的错误信息
Couldn't match type ‘[Char]’ with ‘Char’ Expected type: [String] Actual type: [[String]]
第一个似乎表明我无法摆脱IO,最后一条消息似乎表明lines 将返回一个字符串列表,这也没有意义我。
我怎样才能正确地做到这一点?
【问题讨论】:
-
你确实无法摆脱
IO(或者至少你应该尽量不要那样做)。有unsafeIO,但这通常会产生比它解决的更多的麻烦。 -
不要尝试
run :: [String]。相反,采用函数foo :: [String] -> blah,它将run的内容作为参数,并根据需要使用fmap或(=<<)将其转换为wrappedFoo :: IO [String] -> blah,然后将其应用于run :: IO [String]。 -
Haskell 强制你声明你执行 IO in type,如果你真的执行 IO。声明
run :: [String]等于承诺run没有IO,并且是一个“纯”常量字符串列表。如果你想做IO,你需要声明run :: IO [String],告诉编译器这依赖于IO,并且可以多次执行,可能有不同的结果(如果"play.txt"改变了它的内容)。跨度>
标签: haskell io monads file-read do-notation