首页 > 解决方案 > Haskell IO 字符串 -> 字符串

问题描述

我有以下功能:

getBoard :: String
getBoard = do
    contents <- readFile "src/board.txt"
    return contents

我收到了这个错误:

• 无法将类型“IO”与“[]”匹配预期类型:[String] 实际类型:IO 字符串

已经在互联网上阅读了很多东西,显然我的代码应该可以工作。谁能告诉我怎么了?

Obs:当我去 repl 做:

contents <- readFile "src/board.txt"

接着:

:type contents

它告诉我内容是一个字符串。所以,我无法弄清楚为什么我会收到上面提到的错误。

注意:getBoard 函数必须返回一个字符串

标签: haskell

解决方案


你写过:

getBoard :: String

这并不是说这getBoard是一个返回 a 的函数或过程String。相反,它说这getBoard 一个String; 我的意思是一些特定的Stringlike "Hello world"or "foo",例如。显然,这是错误的。相反,getBoard您可以执行的过程会产生 aString作为其结果。在 Haskell 中,你这样说是:

getBoard :: IO String

所以这是正确的答案。如果该答案对您不起作用,请提供更多上下文,以便我们了解原因。

当你说“注意:getBoard 函数必须返回一个字符串”时,这几乎就是什么getBoard :: IO String意思:getBoard是一个返回String. (这里有一个微妙的点是我说的是“过程”而不是“函数”。那是因为在 Haskell 中,“函数”的含义与您可能对其他语言的期望不同。函数是带有参数的东西。因为getBoard不带参数,所以不是函数,而是过程。)

你的意思是你希望它一个String,而不是返回一个?不过,这没有多大意义。String你希望它是哪个具体的?


好的,现在是我不情愿地承认有一种方法可以告诉 Haskell(错误地)这getBoard是一个String. 你不应该这样做,除非你是一个非常高级的 Haskell 程序员,理解其中的含义,并且有充分的理由这样做是值得的。但是您可以导入System.IO.Unsafe然后getBoundsunsafePerformIO函数包装定义。它的意思是:“假装这getBounds是一些特定String的而不是程序。任何时候你需要知道String它是什么时,偷偷溜到幕后运行这个程序来找出答案。”

请注意,如果您这样做,则无法保证您的程序何时读取文件,程序读取文件的次数,甚至您的程序是否会读取文件!所有这些都取决于评估的严格性、编译器内联等优化选择等等。如果在程序运行时文件的内容发生了变化,结果是不确定的。这不是编写 Haskell 的正常方式,其他 Haskell 程序员会给你奇怪的表情,并假设你在没有充分理由的情况下这样做是无能为力的,你可能应该忘记它,直到你更多地了解先进的一面。我之所以提到它,是因为我不想给出不完整的答复。


推荐阅读