大多数惯用的实现`[a - > a] - >(a - > a)`

Joa*_*ner 4 haskell function function-composition

如果我有一个功能列表,每种类型a -> a的某种类型,最简洁,优雅和惯用的方式组合它们; 最好不要添加额外的依赖项?

一些变体包括

foo (x:xs) = x . (foo xs)
foo [] = id
Run Code Online (Sandbox Code Playgroud)

foo = foldr (.) id
Run Code Online (Sandbox Code Playgroud)

foo = appEndo . mconcat . map Endo
Run Code Online (Sandbox Code Playgroud)

但由于某种原因,我期待找到更好的东西.

Dan*_*zer 19

我会说你不打算打败

comp = foldr (.) id
Run Code Online (Sandbox Code Playgroud)

为什么?好吧,我们有一个列表,我们正试图以正确的关联方式减少它.

如果你看一下的实现and,sum,maximum和类似的,你会看到,这是他们如何在标准库中实现的,我不认为你比这更地道:)

Tangent:我不愿意添加foldr1评论中提到的变体,因为我会说这是意外的行为,maximum因为这显然是必须的.


Ørj*_*sen 6

另一个,可能不短,foldr (.) id但我觉得很可爱:

foo = flip (foldr id)
Run Code Online (Sandbox Code Playgroud)

  • 为了更加清楚,`id`的使用通常被称为`($)`.`($)`只是`id`,具有更具体的类型(`(a - > b) - > a - > b`而不是`a - > a`).我相信他在这里使用`id`因为它更短.写出来时,这个解决方案可以写成`foo lx = foldr($)xl`.这允许你看看发生了什么,即`foo lx = l1 $ l2 $ l3 $ l4 $ .. ln $ x`,这当然与`(l1.l2.l3.l4 ... .. ln )x`这是jozefg的解决方案. (4认同)
  • 对于那些最初感到困惑的人(像我一样),使用`id`作为类型`a - > b - > b`的函数,使用类型`b - > b`来表示类型`a`.所以foldr id(foldr的类型是(`a - > b - > b) - > b - > [a] - > b`),有类型`b - > [b - > b] - > b`,所以`flip(foldr id)`的类型为`[c - > c] - > c - > c`,与`[c - > c] - >(c - > c)相同 (3认同)