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

时间:2015-09-24 08:44:26

标签: haskell f# functional-programming ocaml ml

我正在考虑这样的功能:

> 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#库中但是它存在于其他语言中我想使用相同的名称

4 个答案:

答案 0 :(得分:7)

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

  • 搜索Int -> (a -> a) -> a -> a会显示多个功能可以执行您想要但不属于stdlib的功能。

  • 搜索applyN返回的函数与您正在查找的类型签名完全相同。

  • 通过搜索Int -> (a -> a) -> a laxing返回值(注意最后丢失的-> a),得到erdeszt已经提到的iterateN :: Int -> (a -> a) -> a -> Seq a函数。< / p>

P.S。 Hoogle似乎更有能力翻转参数顺序:(a -> a) -> Int -> a -> Seq a成功返回&#39; iterateN :: Int - &gt; (a - &gt; a) - &gt; a - &gt; Seq a`,Hayoo没有。

答案 1 :(得分:3)

Data.Sequence模块中的Haskell有一个iterateN函数,看起来就像你要查找的那个。

它实际上只是一个迭代+结合的组合: @using Orchard.Blogs.Models @using Orchard.MediaLibrary.Fields @using Orchard.Users.Models @using Orchard.Utility.Extensions @{ // Standard Orchard stuff here... if ( Model.Title != null ) { Layout.Title = Model.Title; } Model.Classes.Add("content-item"); var contentTypeClassName = ( (string)Model.ContentItem.ContentType ).HtmlClassify(); Model.Classes.Add(contentTypeClassName); var tag = Tag(Model, "article"); // And here we go: // Get the blogPost var blogPostPart = (BlogPostPart)Model.ContentItem.BlogPostPart; // Either access the creator directly var blogPostAuthor = blogPostPart.Creator; // Or go this way var blogPostAuthorAsUserPart = ( (dynamic)blogPostPart.ContentItem ).UserPart as UserPart; // Access your UserExtensions part var userExtensions = ( (dynamic)blogPostAuthor.ContentItem ).UserExtensions; // profit var profilePicture = (MediaLibraryPickerField)userExtensions.ProfilePicture; } @tag.StartElement <header> @Display(Model.Header) @if ( Model.Meta != null ) { <div class="metadata"> @Display(Model.Meta) </div> } <div class="author"> <img src="@profilePicture.FirstMediaUrl"/> </div> </header> @Display(Model.Content) @if ( Model.Footer != null ) { <footer> @Display(Model.Footer) </footer> } @tag.EndElement 这是f#版本的迭代(from here),Seq.take是F#标准库的一部分:

let iterateN n f x = take n (iterate f x)

答案 2 :(得分:1)

可能的解决方案:

> 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可以在恒定的空间中迭代,例如当f :: Int -> Int(和f本身在恒定空间中工作时),但上述方法仅适用于线性空间。

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

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)

答案 3 :(得分:0)

要添加其他方法列表,

import Control.Monad.State.Lazy

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