Haskell- 接受函数列表的函数

Haskell- function that accepts a list of functions

我需要编写一个接受函数列表和一个值作为参数的函数。列表中的每个函数都必须依次应用于该值。

例如,如果我的函数被调用 compFuncs...

compFuncs [f,g,h] val等同于f(g(h val))

我已经知道使用 foldr 在这里很有用,我可以将 . 运算符放在函数列表中的每个函数之间,然后将其应用于 val .但是,我无法完成,这是我的尝试...

compFuncs :: [(a->a->a)] -> a -> a
compFuncs [] val = val
compFuncs (x:xs) val = foldr //Im lost here

有人可以帮帮我吗?

(我相信您打算将类型写成 composeFuncs :: [a -> a] -> a -> a,因为它是这样使用的。)

foldr 的工作原理是将列表的构造函数替换为您指定的替换项。例如,foldr (+) 0 [1,2,3] 的工作方式是获取列表 [1,2,3],它实际上构造为 1:2:3:[],并将 (:) 替换为 (+) 并将 [] 替换为0如下:

1 : 2 : 3 : []
1 + 2 + 3 + 0

如果您考虑要将函数列表 [f,g,h] 应用于某个值 \x -> f (g (h x)),我们可以通过寻找 [=23] 的替代项来找到 foldr =] 和 []。首先,让我们使用组合:

\x -> f (g (h x))
= (definition of (.))
\x -> (f . g . h) x
= (eta reduction)
f . g . h

这很接近,但我们必须对空列表构造函数做些事情。我们需要用某种 "do nothing" 或 "empty" 函数替换它。幸运的是,我们有 id,保证不会以任何方式改变结果:

f . g . h
= (definition of id)
f . g . h . id

现在我们可以看到弃牌了:

f . g . h . id
f : g : h : []

我们写成:

composeFuncs :: [a -> a] -> a -> a
composeFuncs = foldr (.) id

顺便说一句,可以像这样折叠的类型与一个用作 "identity" 的元素被称为幺半群*,而 a -> aEndo 幺半群。

* 还有一个附加要求,即用于组合值的函数,如 (.) 对应 Endo(+) 对应 Sum,是关联的。您会注意到,这让我可以在不需要上面括号的情况下展示它们。

编辑

要了解此功能的另一种方法,让我们使用 GHC 7.8 的新类型孔功能。首先,我们从 composeFuncs 的定义开始,有一些漏洞:

composeFuncs :: [a -> a] -> a -> a
composeFuncs = foldr _f _z

当 GHC 类型检查这个时,我们得到一个类型错误,我将把它减少到相关行:

tmp.hs:6:22: Found hole ‘_f’ with type: (a -> a) -> (a -> a) -> a -> a …
tmp.hs:6:25: Found hole ‘_z’ with type: a -> a …

_z开始,类型a -> a只有一个可能的函数,那就是id。对于_f,我们需要一个函数,将两个函数结合起来,给出一个新的函数。那当然是(.),所以我们写:

composeFuncs :: [a -> a] -> a -> a
composeFuncs = foldr (.) id