是否有用于多次应用转换的标准高阶函数?

Is there a standard higher order function for applying a transformation several times?

我在想这样的函数:

> let applyN (initial : 't) (n:int) (f : 't -> 't) = seq {1..n} |> Seq.fold (fun s _ -> f s) initial;;

val applyN : initial:'t -> n:int -> f:('t -> 't) -> 't

> applyN 0 10 (fun x -> x + 1);;
val it : int = 10

注意:代码是 F# 但我用 haskell、ocaml 和 ml 标签标记了问题,因为如果 F# 库中不存在该函数但它存在于其他语言中,我想使用同名

Data.Sequence 模块中有一个用于 Haskell 的 iterateN 函数,看起来像您正在寻找的那个。

其实就是iterate + take的组合: let iterateN n f x = take n (iterate f x) 这是迭代的 F# 版本 (from here),Seq.take 是 F# 标准库的一部分:

let rec iterate f value = seq { 
   yield value
   yield! iterate f (f value) }

可能的解决方案:

> import Data.Monoid
> import Debug.SimpleReflect -- not really needed, just for showing the result
> (appEndo . mconcat . replicate 5 . Endo $ f) a
f (f (f (f (f a))))

另一个(已经提到):

> iterate f a !! 5
f (f (f (f (f a))))

(如果你想把它变成一个函数,请添加 lambdas)

但是,不要忘记 Haskell 是惰性的:上述方法将首先通过多次应用 f 来构建一个 thunk,然后才开始评估。有时 f 可以在常量 space 中迭代,例如当 f :: Int -> Int(并且 f 本身以常量 space 工作)时,但上述方法仅在线性 space.

中工作

我会通过自己的严格迭代组合器来定义,例如:

iter :: Int -> (a -> a) -> a -> a
iter 0 _ x = x
iter n f x = iter (pred n) f $! f x

甚至,

iter n f x = foldl' (flip $ const f) x [1..n]

这是问题中已发布内容的 Haskell 翻译。

或者,我们可以定义 iterate 的严格版本(恕我直言应该已经存在...)

iterate' :: (a -> a) -> a -> [a]
iterate' f x = x : (iterate' f $! f x)

你会得到(非常接近)答案,例如使用 Hayoo(或 Hoogle,但 Hoogle 不那么灵活 — iterateN未找到):

  • Int -> (a -> a) -> a -> a 的搜索揭示了几个功能,它们可以执行您想要的操作,但不属于标准库。

  • 搜索 applyN returned 一个与您正在查找的类型签名完全相同名称的函数。

  • 通过搜索 Int -> (a -> a) -> a 来放宽 return 值(注意末尾缺少的 -> a),您会得到 iterateN :: Int -> (a -> a) -> a -> Seq a erdeszt 已经提到的功能。

P.S。 Hoogle 似乎更有能力翻转参数顺序:(a -> a) -> Int -> a -> Seq a 成功 returns 'iterateN :: Int -> (a -> a) -> a -> Seq a`, Hayoo 没有。

要添加到其他方法列表中,

import Control.Monad.State.Lazy

applyN initial n =
  flip execState initial . replicateM_ n . modify