如何在 zip 生成的列表上折叠 io 操作以打印 2 列?
How to foldl an io operation on a list generated by a zip in order to print 2 columns?
我看到了几个关于使用 foldl 和 IO 的问题,但其中 none 似乎为我的案例提供了解决方案。
我只是想输出两列数字。
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 的想法是在你遍历列表时保持某种状态,但在你的情况下没有状态要保持:你只需要按顺序对每个元素执行一个效果,并且独立于其他元素。
为此,use mapM_
:
printPixel :: (Int, Int) -> IO()
printPixel (i, j) = putStrLn $ (show i) ++ " " ++ (show j)
printPixels :: [(Int, Int)] -> IO()
printPixels colors = mapM_ printPixel colors
或 its twin for_
,这是同一回事,但参数的顺序相反(和较弱的约束),这使您可以将效果作为 lambda 表达式提供,但没有括号,使其看起来差不多像 C 类语言中的 for
结构:
printPixels :: [(Int, Int)] -> IO()
printPixels colors = for_ colors $ \(i, j) -> putStrLn $ (show i) ++ " " ++ (show j)
我看到了几个关于使用 foldl 和 IO 的问题,但其中 none 似乎为我的案例提供了解决方案。
我只是想输出两列数字。
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 的想法是在你遍历列表时保持某种状态,但在你的情况下没有状态要保持:你只需要按顺序对每个元素执行一个效果,并且独立于其他元素。
为此,use mapM_
:
printPixel :: (Int, Int) -> IO()
printPixel (i, j) = putStrLn $ (show i) ++ " " ++ (show j)
printPixels :: [(Int, Int)] -> IO()
printPixels colors = mapM_ printPixel colors
或 its twin for_
,这是同一回事,但参数的顺序相反(和较弱的约束),这使您可以将效果作为 lambda 表达式提供,但没有括号,使其看起来差不多像 C 类语言中的 for
结构:
printPixels :: [(Int, Int)] -> IO()
printPixels colors = for_ colors $ \(i, j) -> putStrLn $ (show i) ++ " " ++ (show j)