zipWith
is your missing function:
reduce fs (x:xs) = foldl (flip id) x $ zipWith flip fs xs
Basically, create a list of single argument functions by combining the operators with the input values (using flip so the value is used as the second argument rather than the first). The rest is the same as your function.
Just a design note, currently the function isn't total - if you pass an empty list for the values the only value that can be returned is bottom (ie undefined
). This is because there is no way to create an a
value. A function like this may be better:
reduce2 :: [a -> b -> a] -> a -> [b] -> a
reduce2 fs x xs = foldl (flip id) x $ zipWith flip fs xs
Since the first value is passed separately, either of the lists can be empty and the function will still complete (it will just ignore values it doesn't need if one of the lists is shorter than the other). It is also more general, in that the list of values may have a different type to the result of the function.