0

我目前正在尝试从电子书 Haskell School of Music 中解决这个问题:

定义一个函数 applyAll,给定一个函数列表 [ f1, f2, ..., fn ] 和一个值 v,返回结果 f1 (f2 (...(fn v)...))。

例如: applyAll [简单 2 2, (+3)] 5 ⇒ 20

目前我有

simple       :: Integer -> Integer -> Integer -> Integer
simple x y z = x * (y + z)

applyAll          :: [(f -> a)] -> a -> a
applyAll [f] v  = foldr (.) v [f]

a = (applyAll [simple 2 2, (+3)] 5)
print a

这给了我错误:

Couldn't match type `f' with `a0 -> f'
  `f' is a rigid type variable bound by
      the type signature for applyAll :: [f -> a] -> a -> a

Expected type: (f -> a) -> a -> a
  Actual type: (f -> a) -> (a0 -> f) -> a0 -> a
In the first argument of `foldr', namely `(.)'
In the expression: foldr (.) v [f]

我假设它与类型签名有关,但到目前为止我没有尝试过任何结果。

4

1 回答 1

3

这里的问题是类型.(b->c) -> (a->b) -> a -> c但我们折叠的初始值不是函数。用英语说,.就是函数组合,但我们要函数应用。然而,这很容易解决($)

($) f a = f a

所以

applyAll :: [(f -> a)] -> a -> a
applyAll [f] v  = foldr ($) v [f]

接下来我们的零件有问题[f]。所做的只是匹配一个可能不是您想要的元素列表。

applyAll fs v = foldr ($) v fs

现在我们需要处理最后一部分,类型签名。我们的函数不能接收类型函数,f -> a因为当我们连接它们时,我们会在函数a需要一个f. 所以最终的结果是

 applyAll :: [a -> a] -> a -> a
 applyAll fs v = foldr ($) v fs
于 2013-06-10T02:47:44.383 回答