提问人:not_existent 提问时间:1/17/2023 更新时间:1/17/2023 访问量:93
如何在非 IO 函数中使用 IO 操作的结果?
How can I use the result of an IO action in an non-IO-function?
问:
此函数采用文件路径并返回文件的内容。 此文件包括一组相同长度的线条。 -- 它曾经是一张原始的图片。
parsePicture :: FilePath -> IO()
parsePicture fileName = do
content <- lines <$> readFile fileName
print content
现在,我尝试实现一个垂直翻转“图片”的函数:
type Picture = [[Char]]
flipVertical :: IO() -> Picture
flipVertical xs = map reverse xs
但我只收到以下错误代码:
zuP12.hs:24:31: error:
• Couldn't match expected type ‘[[Char]]’ with actual type ‘IO ()’
• In the second argument of ‘map’, namely ‘xs’
In the expression: map reverse xs
In an equation for ‘flipVertical’: flipVertical xs = map reverse xs
|
24 | flipVertical xs = map reverse xs
| ^^
Failed, no modules loaded.
如何在parsePicture的结果上使用我的函数flipVertical?
答:
5赞
leftaroundabout
1/17/2023
#1
这个功能...返回文件的内容。
不,它没有。它将文件的内容打印到 STDOUT。在大多数情况下,您应该认为您放入 STDOUT 的信息已经消失——该信息已经离开您的程序,现在位于终端屏幕上,或者用户选择放置它的任何位置,但程序无法再访问。
(严格来说,可以将 STDOUT 重定向回您自己的程序,但这是一个很大的黑客,不要这样做。
相反,您应该更改函数,以便它实际上返回内容:
parsePicture :: FilePath -> IO Picture
parsePicture fileName = do
content <- lines <$> readFile fileName
return content
...或者干脆
parsePicture fileName = lines <$> readFile fileName
其行为完全相同(根据 Monad 定律)。
另外,我宁愿称之为:解析不应该涉及文件读取。loadPicture
当然,您以后仍然可以打印内容,例如
main = do
...
fooPicture <- parsePicture "foofilename"
print fooPicture
...
至于,这应该与此完全无关。它只是一个纯函数flipVertical
IO
flipVertical :: Picture -> Picture
flipVertical xs = map reverse xs
例如,可以像这样使用
main = do
...
fooPicture <- parsePicture "foofilename"
print $ flipVertical fooPicture
...
或
main = do
...
fooVFPicture <- flipVertical <$> parsePicture "foofilename"
...
评论
1赞
user253751
1/17/2023
吹毛求疵:您打印的信息仍在程序中 - 但前提是您将其保留在某个变量中 - 打印它没有区别。
评论
IO
IO Something -> NonIOType
IO
f :: Int -> Int
f :: Int -> IO Int