haskell - 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 函数必须返回一个字符串
解决方案
你写过:
getBoard :: String
这并不是说这getBoard
是一个返回 a 的函数或过程String
。相反,它说这getBoard
是一个String
; 我的意思是一些特定的String
like "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
然后getBounds
用unsafePerformIO
函数包装定义。它的意思是:“假装这getBounds
是一些特定String
的而不是程序。任何时候你需要知道String
它是什么时,偷偷溜到幕后运行这个程序来找出答案。”
请注意,如果您这样做,则无法保证您的程序何时读取文件,程序读取文件的次数,甚至您的程序是否会读取文件!所有这些都取决于评估的严格性、编译器内联等优化选择等等。如果在程序运行时文件的内容发生了变化,结果是不确定的。这不是编写 Haskell 的正常方式,其他 Haskell 程序员会给你奇怪的表情,并假设你在没有充分理由的情况下这样做是无能为力的,你可能应该忘记它,直到你更多地了解先进的一面。我之所以提到它,是因为我不想给出不完整的答复。
推荐阅读
- python - 无法开始使用 VSCode 和 Python 3.9
- javascript - 在 vue.js 中设置过滤器
- python - Turtle 不会在 PyCharm 中绘图
- mysql - 无法从其他容器连接到 MySQL 容器
- python - 如何让 Pylance 忽略 None 的可能性?
- java - Java Firebase 获取 RealtimeDatabase 值
- apache-spark - --master local[K] 和 --conf spark.executor.cores 如何确定线程数?
- python - 使用 Rust 的 `run_cmd` 在 `glob` 返回的迭代器上运行脚本
- node.js - 如何使用“child_process”从 NodeJS 脚本(带参数)启动 VLC?
- javascript - ReferenceError 切换未定义 | '$' 已定义但从未使用过。(no-unused-vars) eslint | 'toggle' 已定义但从未使用过。(没有未使用的变量)