我有以下代码,它采用一个列表,检查每个元素的值是否高于avg
,并且在这种情况下,打印val - avg
。我已经用递归实现了它,我想转换它以便使用map
函数。
loop [] = return ()
loop (x:xs)
| x > average = print (x - average) >> loop xs
| otherwise = loop xs
有什么建议吗?
答案 0 :(得分:7)
请注意,loop
的每一步都会同时执行两项操作:它们(可能)从列表的每个元素生成打印操作,然后将该操作与其余元素组合在一起(使用(>>)
)。如果你想用loop
来写map
,你需要解开这两个子步骤。例如,您可以定义一个函数......
printDiffIfAboveAvg :: Double -> IO ()
...然后使用map printDiffIfAboveAvg
将其应用于列表的所有元素。这将为您提供类型为[IO ()]
的操作列表,您需要将这些操作合并为一个整体操作:
runAllActions :: [IO ()] -> IO ()
runAllActions
已经存在于基础库中,在更通用的版本sequence_
中:
sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
所以你会loop = sequence_ . map printDiffIfAboveAvg
。实际上,基础库中还有另一个功能......
mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
...正好执行sequence_
和map
的组合。