Haskell 读取文件的每一行

21
我想把整个文件读入一个字符串,然后使用函数lines来获取该字符串的行。我正在尝试使用以下代码行实现:
main = do
   args <- getArgs
   content <- readFile (args !! 0)
   linesOfFiles <- lines content

但是我编译失败了,出现了以下错误:
Couldn't match expected type `IO t0' with actual type `[String]'
In the return type of a call of `lines'
In a stmt of a 'do' block: linesOfFiles <- lines content

我以为将readFile的结果绑定到content变量上后,它会变成一个String数据类型,为什么不是呢?

1个回答

53
我认为通过将readFile的结果绑定到content,它将成为一个字符串数据类型,但为什么不是呢?
它确实是一个字符串(String)类型,编译器抱怨的并不是这个。让我们来看看代码:
main = do
   args <- getArgs
   content <- readFile (args !! 0)

现在,content已经按预期成为一个普通的String。然后,lines content是一个[String]。但是在接下来的一行中,您正在使用单子(monadic)绑定。

   linesOfFiles <- lines content
在一个 IO () do 块中,编译器期望在 <- 的右侧找到一个类型为 IO something 的表达式,但实际上却找到了一个 [String] 类型的表达式。
由于计算 lines content 没有涉及任何 IO 操作,因此你应该使用 let 绑定来绑定它的结果,而不是使用单子绑定。
   let linesOfFiles = lines content

那一行是你需要的。


此外,为了完整性,请将其与getArgs和readFile的类型进行比较。 - Gabriella Gonzalez
这个解决方案是如何工作的?你不能将content传递给lines,因为lines的类型是String -> [String],而content的类型是IO String - kjh
2
@kjh 不是的,content 是一个 String 类型。readFile (args !! 0) 的类型是 IO String,我们将 content 绑定到那个 IO 动作的“结果”上。do { a <- action; stuff; } 结构会被转换成 action >>= \a -> stuff ,如果 action 的类型是 IO t,那么 a 的类型就是 t - Daniel Fischer
我明白了。谢谢你的澄清。 - kjh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接