将函数 n 次应用于 haskell 列表中的第 n 项

apply a function n times to the n-th item in a list in haskell

我想要一个高阶函数 g,它会将另一个函数 f 应用于整数列表,使得

g = [f x1, f(f x2), f(f(f x3)), … , f^n(xn)]

我知道我可以映射一个像

这样的函数
g :: (Int -> Int) -> [Int] -> [Int]
g f xs = map f xs

我也可以像

一样应用n次函数
g f xs = [iterate f x !! n | x <- xs]

其中 n 是应用函数的次数。我知道我需要使用递归,所以我认为这些选项都没有用。

预期输出:

g (+1) [1,2,3,4,5] = [2,4,6,8,10]

您可以使用显式递归,每次都传递要应用的函数和列表的尾部,因此:

g :: (Int -> Int) -> [Int] -> [Int]
g f = go f
    where go _ [] = []
          go fi (x:xs) = … : go (f . fi) xs

我在这里将实现 部分作为练习。

另一种选择是使用两个列表,一个函数列表和一个值列表。在这种情况下,函数列表是 iterate (f .) f:可以应用的无限函数列表。那么我们可以将g实现为:

g :: (Int -> Int) -> [Int] -> [Int]
g f = zipWith ($) (iterate (f .) f)

听起来像是 foldr 的另一个用途:

applyAsDeep :: (a -> a) -> [a] -> [a]
applyAsDeep f = foldr (\x xs -> f x : map f xs) []

λ> applyAsDeep (+10) [1,2,3,4,5]
[11,22,33,44,55]

如果你想有点矫枉过正......

import GHC.Exts (build)

g :: (a -> a) -> [a] -> [a]
g f xs0 = 
  build $ \c n -> 
    let go x r fi = fi x `c` r (f . fi) 
    in foldr go (const n) xs0 f