繁体   English   中英

如何在 zip 生成的列表上折叠 io 操作以打印 2 列?

[英]How to foldl an io operation on a list generated by a zip in order to print 2 columns?

我已经看到了几个关于使用 foldl 和 IO 的问题,但它们似乎都没有为我的案例提供解决方案。

我只是想 output 两列数字。

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 的想法是在遍历列表时保留某种 state ,但在您的情况下,没有要保留的 state :您只需要按顺序为每个元素执行效果,并且独立于其他元素。

为此,请使用mapM_

printPixel :: (Int, Int) -> IO()
printPixel (i, j) = putStrLn $ (show i) ++ " " ++ (show j)

printPixels :: [(Int, Int)] -> IO()
printPixels colors = mapM_ printPixel colors

或者它的双胞胎for_ ,这是同一件事,但 arguments 的顺序相反(和较弱的约束),这使您可以将效果作为 lambda 表达式提供,但没有括号,使其看起来几乎像 C 中的for构造-喜欢语言:

printPixels :: [(Int, Int)] -> IO()
printPixels colors = for_ colors $ \(i, j) -> putStrLn $ (show i) ++ " " ++ (show j)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM