Reputation: 15
I'm currently attempting to do this problem from the ebook, Haskell School of Music:
Define a function applyAll that, given a list of functions [ f1, f2, ..., fn ] and a value v, returns the result f1 (f2 (...(fn v)...)).
For example: applyAll [simple 2 2, (+3)] 5 ⇒ 20
Currently I have
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
Which gives me the error:
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]
I'm assuming it has something to do with the type signature, but nothing I've tried so far has yielded results.
Upvotes: 0
Views: 307
Reputation: 53911
The problem here is that the type of .
is (b->c) -> (a->b) -> a -> c
but our initial value for our fold is not a function. To put this in english, .
is function composition, but we want function application. This is easily solved however with ($)
.
($) f a = f a
so
applyAll :: [(f -> a)] -> a -> a
applyAll [f] v = foldr ($) v [f]
Next we have a problem with the [f]
part. All that does is match a single element list which is probably not what you want.
applyAll fs v = foldr ($) v fs
Now we need to deal with one last part, the type signature. Our function can't take in functions of type f -> a
because when we connect them we'll feed a function a value of type a
when it expects an f
. So the end result is
applyAll :: [a -> a] -> a -> a
applyAll fs v = foldr ($) v fs
Upvotes: 3