Question

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.

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top