2016-01-19 4 views
0

Я пишу функцию, которая суммирует элементы списка кортежей, как это:Работы с кортежами и привязками

sumAll [(2,4,11), (3,1,-5), (10,-3,6)] = (15,2,12) 

У меня есть это:

sumAll :: (Num a, Num b, Num c) => [(a,b,c)] -> (a,b,c) 
sumAll l = (foldr (+) 0 as, foldr (+) 0 bs, foldr (+) 0 cs) 
       where trd (a,b,c) = c 
        as = (map (fst) l) 
        bs = (map (snd) l) 
        cs = (map (trd) l) 

Однако компилятор жалуется:

Couldn't match type `(a, b, c)' with `(b1, b0)' 
    Expected type: [(b1, b0)] 
     Actual type: [(a, b, c)] 
    Relevant bindings include 
     as :: [b1] (bound at ficha3.hs:22:22) 
     cs :: [c] (bound at ficha3.hs:24:22) 
     l :: [(a, b, c)] (bound at ficha3.hs:20:12) 
     sumAll :: [(a, b, c)] -> (a, b, c) (bound at ficha3.hs:20:1) 
    In the second argument of `map', namely `l' 
    In the expression: (map (fst) l) 

И то же самое для выражения (map (snd) l).

Если я удаляю параметры 'c' из определения функции, оно работает. Как это:

sumAll :: (Num a, Num b) => [(a,b)] -> (a,b) 
sumAll l = (foldr (+) 0 as, foldr (+) 0 bs) 
       where as = (map (fst) l) 
        bs = (map (snd) l) 

Мои вопросы, если это возможно:

  1. Почему «с» «завинчивание» выходной кортеж?
  2. Как я могу это сделать?
+0

Комментарий стиля: '(map (fst) l)' чаще всего записывается 'map fst l' - никаких скобок не требуется. – chi

+0

Равномерные кортежи немного раздражают, если вы хотите применить операцию ко всем элементам. Если вы использовали списки вместо кортежей, вы можете написать 'sumAll' просто как' foldr (zipWith (+)) [0, 0 ..] :: Num a => [[a]] -> [a] '. Однако самый короткий список входных данных будет определять длину вывода. –

ответ

4

Рассмотрим, как ваш fst, snd и trd определены. Если вы используете fst от Prelude, тогда у него есть тип fst :: (a, b) -> a, который не работает для 3-х кортежей.

+0

Функции fst и snd переопределены. Спасибо! –

Смежные вопросы