import System.Environment
import qualified Data.Vector.Unboxed as V
import Data.Vector.Unboxed (Vector)
display :: Vector Double -> String
display ds | V.null ds = ""
| otherwise = tail . concatMap format . V.toList $ ds
where format d = ',' : show d
csv_sums :: String -> Vector Double
csv_sums input = go (V.length $ h) 1 h t where
h : t = map (V.fromList . read . bracket) $ lines input
bracket s = '[' : s ++ "]"
go s n summary [] = summary
go s n summary (x:xs)
| V.length x == s = go s (n + 1) (V.zipWith (+) summary x) xs
| otherwise = if blankLastLine then summary
else error "Inconsistent lengths."
where blankLastLine = case xs of [] -> V.length x == 0
_ -> False
main = do
paths <- getArgs
if length paths /= 1
then error "Exactly one filename must be given."
else readFile (head paths) >>= putStrLn . display . csv_sums
It takes about 22x longer than Python on my platform though, which I'm not sure how to solve. (The vector keeps it nice and un-thunked so it doesn't seem like it's laziness that's killing it, maybe it's the use of strings over Data.ByteString.Lazy or so?)
The main problem is probably creating and traversing the strings, although I have not benchmarked it. This version
https://gist.github.com/Codas/894694eea247aaacf35f
runs about 4 times faster than the python version on my machine.
It does use some libraries that are not in the haskell platform though.