Haskell-接受函数列表的函数

时间:2015-03-03 18:09:44

标签: haskell

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

例如,如果我的函数被称为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

有人可以帮帮我吗?

1 个答案:

答案 0 :(得分:8)

(我相信您打算将类型写为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)),我们可以通过查找foldr的替换项找到(:)[]。首先,让我们使用构图:

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

这很接近,但我们必须对空列表构造函数执行某些操作。我们需要用某种“无所事事”或“空”功能来代替它。幸运的是,我们有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

顺便说一下,可以像这样折叠的类型和一个充当“身份”的元素被称为monoids *,而a -> aEndo monoid。

*还有一项要求是,用于组合值的函数(例如(.)的{​​{1}}或Endo的{​​{1}})是关联的。你会注意到这使我能够在不需要括号的情况下展示它们。

修改

对于发现此功能的另一种方法,让我们使用GHC 7.8的新型孔功能。首先,我们从(+)开始定义一些漏洞:

Sum

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

composeFuncs

composeFuncs :: [a -> a] -> a -> a composeFuncs = foldr _f _z 开始,只有一种类型为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
相关问题