import Data.List (transpose)
import Data.Array ((!),accumArray,elems,listArray)
-- 1ª definición (por recursión):
sumaPolinomios1 :: Num a => [[a]] -> [a]
sumaPolinomios1 [] = []
sumaPolinomios1 [xs] = xs
sumaPolinomios1 (xs:ys:zss) = suma xs (sumaPolinomios1 (ys:zss))
-- (suma xs ys) es la suma de los vectores xs e ys. Por ejemplo,
-- suma [4,7,3] [1,2,5] == [5,9,8]
suma :: Num a => [a] -> [a] -> [a]
suma [] [] = []
suma (x:xs) (y:ys) = x+y : suma xs ys
-- 2ª definición (por recursión con zipWith):
sumaPolinomios2 :: Num a => [[a]] -> [a]
sumaPolinomios2 [] = []
sumaPolinomios2 [xs] = xs
sumaPolinomios2 (xs:xss) = zipWith (+) xs (sumaPolinomios2 xss)
-- 3ª definición (por plegado)
sumaPolinomios3 :: Num a => [[a]] -> [a]
sumaPolinomios3 = foldr1 (zipWith (+))
-- 4ª definición (por comprensión con transpose):
sumaPolinomios4 :: Num a => [[a]] -> [a]
sumaPolinomios4 xss = [sum xs | xs <- transpose xss]
-- 5ª definición (con map y transpose):
sumaPolinomios5 :: Num a => [[a]] -> [a]
sumaPolinomios5 = map sum . transpose
-- 6ª definición (con array)
sumaPolinomios6 :: Num a => [[a]] -> [a]
sumaPolinomios6 xss = [sum [p!(i,j) | i <- [1..m]] | j <- [1..n]]
where m = length xss
n = length (head xss)
p = listArray ((1,1),(m,n)) (concat xss)
-- 7ª definición (con accumArray)
sumaPolinomios7 :: Num a => [[a]] -> [a]
sumaPolinomios7 xss =
elems $ accumArray (+) 0 (1,n) (concat [zip [1..] xs | xs <- xss])
where n = length (head xss)
-- Comparación de eficiencia
-- ghci> sumaPolinomios1 (replicate 300000 (replicate 5 1))
-- [300000,300000,300000,300000,300000]
-- (3.94 secs, 354713532 bytes)
--
-- ghci> sumaPolinomios2 (replicate 300000 (replicate 5 1))
-- [300000,300000,300000,300000,300000]
-- (2.08 secs, 185506908 bytes)
--
-- ghci> sumaPolinomios3 (replicate 300000 (replicate 5 1))
-- [300000,300000,300000,300000,300000]
-- (1.48 secs, 167026728 bytes)
--
-- ghci> sumaPolinomios4 (replicate 300000 (replicate 5 1))
-- [300000,300000,300000,300000,300000]
-- (1.08 secs, 148564752 bytes)
--
-- ghci> sumaPolinomios5 (replicate 300000 (replicate 5 1))
-- [300000,300000,300000,300000,300000]
-- (1.02 secs, 148062764 bytes)
--
-- ghci> sumaPolinomios6 (replicate 300000 (replicate 5 1))
-- [300000,300000,300000,300000,300000]
-- (3.17 secs, 463756028 bytes)
--
-- ghci> sumaPolinomios7 (replicate 300000 (replicate 5 1))
-- [300000,300000,300000,300000,300000]
-- (1.50 secs, 291699548 bytes)