Во-первых, давайте возьмем ваше текущее нерабочее определение:
func :: [(Double,Double)] -> (Double,Double)
func [(x, y)] = map fst (x,y)
В этом есть несколько ошибок:
- Ваше совпадение с шаблоном
[(x, y)]
соответствует толькосписок с ровно одним элементом.Любой список с 2 или более элементами вызовет ошибку, поскольку они не совпадают. map
не может быть применено к кортежам;его можно применять только к спискам. - Даже если вы можете
map
над кортежем, fst
должен применяться непосредственно к кортежу - fst (a, b)
дает a
, тогда как map fst (a, b)
не делает 'не имеет смысла.
Давайте рассмотрим некоторые альтернативные определения.
Понимание списка
func_1 :: [(Double,Double)] -> (Double,Double)
func_1 list =
let fsts = [ a | (a, _) <- list ]
snds = [ b | (_, b) <- list ]
in (sum fsts, sum snds)
Это отдельно выделяет каждый первый элемент из списка, затем каждую секундуэлемент из списка, затем складывает их вместе.
Отображение
func_2 :: [(Double,Double)] -> (Double,Double)
func_2 list =
let fsts = map fst list
snds = map snd list
in (sum fsts, sum snds)
Карты fst
над каждым элементом входного списка, чтобы получить список всех первых элементов списка.Затем сопоставьте snd
, чтобы сделать то же самое для вторых элементов.
Рекурсия
func_3 :: [(Double,Double)] -> (Double,Double)
func_3 [] = (0, 0)
func_3 ((a,b) : xs) =
let (a', b') = func_3 xs
in (a+a', b+b')
Немного другой подход.Списки в Хаскеле формируются рекурсивно: [a, b, c]
эквивалентно (a : (b : (c : [])))
.Это означает, что мы можем использовать сопоставление с образцом, чтобы получить первый элемент списка, а также все другие элементы списка.Это определение работает в двух частях:
- Если в списке нет элементов, просто верните
(0, 0)
( базовый случай ). - Если список имеетхотя бы один элемент, возьмите оставшуюся часть списка (например,
[b, c]
, если было дано [a, b, c]
, или []
, если было дано [a]
), снова вычислите его сумму, используя func_3
, затем добавьте первый элемент обратновкл.