如何在非 IO 功能中使用 IO 操作的结果?

1 io haskell types functional-programming

这个函数接受一个文件路径并返回文件的内容。\n这个文件包含一对相同长度的行。\n-- 它曾经是一个原始图片。

\n
parsePicture :: FilePath -> IO()\nparsePicture fileName = do\n    content <- lines <$> readFile fileName\n    print content\n
Run Code Online (Sandbox Code Playgroud)\n

现在我尝试实现一个垂直翻转“图片”的功能:

\n
type Picture = [[Char]]\n\nflipVertical :: IO() -> Picture\nflipVertical xs = map reverse xs\n
Run Code Online (Sandbox Code Playgroud)\n

但我只收到以下错误代码:

\n
zuP12.hs:24:31: error:\n    \xe2\x80\xa2 Couldn't match expected type \xe2\x80\x98[[Char]]\xe2\x80\x99 with actual type \xe2\x80\x98IO ()\xe2\x80\x99\n    \xe2\x80\xa2 In the second argument of \xe2\x80\x98map\xe2\x80\x99, namely \xe2\x80\x98xs\xe2\x80\x99\n      In the expression: map reverse xs\n      In an equation for \xe2\x80\x98flipVertical\xe2\x80\x99: flipVertical xs = map reverse xs\n   |\n24 | flipVertical xs = map reverse xs\n   |                               ^^\nFailed, no modules loaded.\n
Run Code Online (Sandbox Code Playgroud)\n

如何在 parsePicture 的结果上使用我的函数 FlipVertical?

\n

lef*_*out 5

\n

该函数...返回文件的内容。

\n
\n

不,没有。它将文件的内容打印到 STDOUT。对于大多数用途,您应该考虑将放入 STDOUT 的信息消失\ xe2\x80\x93 该信息已离开您的程序,现在位于终端屏幕上,或者用户选择将其放置在其他任何位置,但程序无法访问不再了。

\n

(严格来说,可以STDOUT 重定向回您自己的程序,但这是一个很大的 hack,不要这样做。)

\n

相反,您应该更改该函数,以便它实际上返回内容:

\n
parsePicture :: FilePath -> IO Picture\nparsePicture fileName = do\n    content <- lines <$> readFile fileName\n    return content\n
Run Code Online (Sandbox Code Playgroud)\n

...或者简单地说

\n
parsePicture fileName = lines <$> readFile fileName\n
Run Code Online (Sandbox Code Playgroud)\n

其行为完全相同(根据单子定律)。

\n

另外,我宁愿这样称呼loadPicture:解析不应该涉及文件读取。

\n

当然,您仍然可以稍后打印内容,例如

\n
main = do\n   ...\n   fooPicture <- parsePicture "foofilename"\n   print fooPicture\n   ...\n
Run Code Online (Sandbox Code Playgroud)\n

至于flipVertical,这应该是没有什么关系的IO。这只是一个纯函数

\n
flipVertical :: Picture -> Picture\nflipVertical xs = map reverse xs\n
Run Code Online (Sandbox Code Playgroud)\n

可以这样使用,例如

\n
main = do\n   ...\n   fooPicture <- parsePicture "foofilename"\n   print $ flipVertical fooPicture\n   ...\n
Run Code Online (Sandbox Code Playgroud)\n

或者

\n
main = do\n   ...\n   fooVFPicture <- flipVertical <$> parsePicture "foofilename"\n   ...\n
Run Code Online (Sandbox Code Playgroud)\n