2017-02-14 13 views
0

Все, что я пытаюсь сделать, это суммировать список списков. Пример того, что я хочу сделать:Ошибка «неисчерпывающих шаблонов» при суммировании списка списков

Входной: [[1,2,3],[2,5],[6,7]]

Выход: [6,7,13]

Количество списков внутри внешнего списка может изменяться, а количество целых чисел в каждом внутреннем списке может изменяться. Я пробовал множество вещей, и это последнее, что я пытался, но он не работает:

sumSubsets [[x]] = map sum [[x]] 

Кроме того, я хотел базовый случай sumSubsets [] = [[]] но что приводит к ошибкам, а также. Любая помощь будет оценена по достоинству.

+0

'карта sum' должно быть достаточно ... – Alec

+0

А хедз-ап: я изменил название лучше отражает основную проблему, и говоря об ошибке, которое (I предположим) вы видели. (В таких случаях всегда полезно процитировать ошибки, которые вы получаете.) – duplode

ответ

2

Вы можете использовать

sumSubsets x = map sum x 

или даже

sumSubsets = map sum 

Ваш предыдущий код,

sumSubsets [[x]] = map sum [[x]] 

Первый выполняет матч с шаблон с помощью [[x]], который соответствует список, содержащий один элемент, который сам список, содержащий один элемент. Поэтому было бы корректно работать на [[3]]

>> sumSubsets [[3]] 
[3] 

, но не на [[1,2,3]] или [[1],[2]].

+0

Woooow, хорошо, я не могу поверить, что квадратные скобки были тем, что испортило его. Я знал, что концепция правильная. ОК. Спасибо. Вопрос, хотя, почему это просто работает x, но [x] или [[x]] нет? – MandyLB

+1

'[[x]]' является шаблоном для списка, содержащего ровно один список, так же как '[x]' - это список с ровно одним элементом. Просто 'x' - любой ввод любой формы. –

+0

Другой вопрос. Может ли код вообще измениться, чтобы иметь выход из [[6], [7], [13]] вместо [6,7,13]? – MandyLB

0

Я думаю, что ваша проблема связана прежде всего с смешиванием типов и ценностей, которые могут легко случиться новичкам, в частности по спискам. Вся путаница, вероятно, исходит из того, что в Haskell [] используется как конструктор данных, так и конструктор типов.

Например, [Int] означает «список Ints» (тип), но [1] означает «список, содержащий один элемент, а именно номер 1» (значение - значение, весь список - это значение) , Обе вещи вместе:

xs :: [Int] 
xs = [1] 

Когда вы пишете полиморфные функции, абстрагироваться от чего-то вроде Int. Например, если вы хотите получить первый элемент списка, вы можете определить функцию, которая делает это для любого типа списка, - могут ли они быть списками целых чисел или списков символов или даже списков списков:

firstElement :: [a] -> a 
firstElement (x:xs) = x 

[a] означает «список с элементами типа a» (тип), а только a означает «нечто типа a». firstElement - это функция из списка с элементами типа a в нечто вроде a. a - это переменная типа.Так как вы не говорите, что a должно быть, функция работает для всех видов списков:

*Main> firstElement [1,2,3] 
1 

*Main> firstElement ['a','b'] 
'a' 

*Main> firstElement [[1,2],[3,4]] 
[1,2] 

Когда вы написали [[x]] вы, возможно, думаете о типе первого аргумента функции, которая была бы список списков элементов некоторого типа x (x - это переменная типа). Вы можете использовать это, но вы должны положить его в сигнатуру типа вашей функции (линии, которая содержит два двоеточия):

sumSubsets :: Num a => [[a]] -> [a] 
sumSubsets xs = map sum xs 

я использовал a здесь вместо x, так как он чаще но вы также можете использовать x. К сожалению, все это немного усложняется с Num a, в котором описаны дополнительные требования к типу a (что он относится к номерам, поскольку для других вещей sum не определен). Для упрощения, можно было бы написать:

sumSubsetsInts :: [[Int]] -> [Int] 
sumSubsetsInts xs = map sum xs