使用map而不是递归

And*_*llo 0 recursion lambda haskell

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

loop [] = return ()
loop (x:xs)
      | x > average = print (x - average) >> loop xs
      | otherwise = loop xs
Run Code Online (Sandbox Code Playgroud)

有什么建议吗?

dup*_*ode 7

请注意,每个步骤同时loop执行两项操作:它们(可能)从列表的每个元素生成打印操作,然后将该操作与其余操作组合(使用(>>)).如果你想写loop来讲map,你需要理清这两个子步骤.例如,您可以定义一个函数......

printDiffIfAboveAvg :: Double -> IO ()
Run Code Online (Sandbox Code Playgroud)

...然后将其应用于列表的所有元素map printDiffIfAboveAvg.这将为您提供类型的操作列表[IO ()],您需要将这些操作合并为一个整体操作:

runAllActions :: [IO ()] -> IO ()
Run Code Online (Sandbox Code Playgroud)

runAllActions已经存在于基础库中,在更通用的版本中称为sequence_:

sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
Run Code Online (Sandbox Code Playgroud)

所以你会的loop = sequence_ . map printDiffIfAboveAvg.实际上,基础库中还有另一个功能......

mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
Run Code Online (Sandbox Code Playgroud)

...执行的正是这种组合sequence_map.