I am implementing a function combine :: [[a]] -> [[b]] -> (a -> b -> c) -> [[c]]
which given two 2D lists, applies a given function f :: a -> b -> c
to the entries of the 2D list. In other words:
[[a, b, c], [[r, s, t], [[f a r, f b s, f c t],
combine [d, e, g], [u, v, w], f = [f d u, f e v, f g w],
[h, i, j]] [x, y, z]] [f h x, f i y, f j z]]
Now I suspect that combine = zipWith . zipWith
, because I have tried it out and it is giving me the intended results, e.g.
(zipWith . zipWith) (\x y -> x+y) [[1,2,3],[4,5,6]] [[7,8,9],[10,11,12]]
gives the expected result [[8,10,12],[14,16,18]]
, but I cannot understand why this works, because I don't understand how the type of zipWith . zipWith
turns out to be (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
.
Is (.)
here still carrying out the usual function composition? If so, can you explain how this applies to zipWith
?