haskell - 如何在 zip 生成的列表上折叠 io 操作以打印 2 列?
问题描述
我已经看到了几个关于使用 foldl 和 IO 的问题,但似乎没有一个可以为我的案例提供解决方案。
我只是想输出两列数字。
0 256
1 256
2 256
...
256 256
0 255
1 255
2 255
3 255
4 255
我尝试了以下方法,但我只能打印一行而不是一整列:
zipMerge :: [a] -> [b] -> [(a,b)]
zipMerge [] _ = []
zipMerge _ [] = error "second list cannot be empty"
zipMerge (a:as) bs = (zip (replicate (length bs) a) bs) ++ (zipMerge as bs)
-- foldl :: (a -> b -> a) -> a -> [b] -> a
printPixel :: IO() -> (Int, Int) -> IO()
printPixel _ (i, j) = putStrLn (show i) ++ " " ++ (show j)
printPixels :: [(Int, Int)] -> IO()
printPixels colors = foldl printPixel (return ()) colors
printGradient :: IO()
printGradient = do
putStrLn "255"
let is = [0..256]
js = [256,255..0]
printPixels (zipMerge js is)
我究竟做错了什么 ?
解决方案
弃牌在这里绝对是矫枉过正。fold 的想法是在遍历列表时保留某种状态,但在您的情况下,没有要保留的状态:您只需要按顺序为每个元素执行效果,并且独立于其他元素。
为此,请使用mapM_
:
printPixel :: (Int, Int) -> IO()
printPixel (i, j) = putStrLn $ (show i) ++ " " ++ (show j)
printPixels :: [(Int, Int)] -> IO()
printPixels colors = mapM_ printPixel colors
或者它的 twinfor_
,这是相同的东西,但是具有相反顺序的参数(和较弱的约束),它可以让您提供作为 lambda 表达式的效果,但没有括号,使其看起来几乎像for
C 语言中的构造:
printPixels :: [(Int, Int)] -> IO()
printPixels colors = for_ colors $ \(i, j) -> putStrLn $ (show i) ++ " " ++ (show j)
推荐阅读
- angular - 不能在未定义上使用地图功能,从订阅返回,服务数据延迟,直到时间地图功能被执行
- javascript - 如何将 AJAX 成功传递给另一个带参数的函数?
- c++ - 如何使用 micro pro 在记事本中打印表情符号
- android - 更改 OutlinedTextField 的边框半径
- php - 在laravel中的两个相关模型中过滤
- visual-studio-2019 - Photino Blazor 应用程序不会在 Program Files 文件夹中运行
- reactjs - 我如何从 if 语句中更改两个不同的东西?
- amazon-web-services - cdk 在 docker 镜像中部署
- javascript - 在滚动时更新鼠标位置
- json - 如何以角度插入从 JSON 对象返回的字符串