使用map而不是递归

时间:2017-02-19 17:54:00

标签: haskell recursion lambda

我有以下代码,它采用一个列表,检查每个元素的值是否高于avg,并且在这种情况下,打印val - avg。我已经用递归实现了它,我想转换它以便使用map函数。

loop [] = return ()
loop (x:xs)
      | x > average = print (x - average) >> loop xs
      | otherwise = loop xs

有什么建议吗?

1 个答案:

答案 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的组合。