data [a] = [] | (a:[a])
Таким образом, это тип данных, который имеет два конструктора:
- пустой список
[]
, который используется для обозначения конца списка; и
cons
, который имеет два элемента: a
(изделие) и ссылку на хвост (a [a]
).
Теперь, когда мы знаем, что вы можете использовать шаблон соответствия для извлечения элементов (и делать тесты). Например, в следующей функции:
head :: [a] -> a
head (x:_) = x
Здесь head
ожидает увидеть cons
конструкцию и извлекает головку (элемент первого узла), и возвращает это. Или, например,:
second :: [a] -> a
second (_:(x:_)) = x
здесь вы снова используете шаблон для извлечения второго элемента.
Другой способ получения элементов - использовать (!!) :: [a] -> Int -> a
. оператор. Вы можете получить я -й элемент (нуля), с помощью:
list!!i
что эквивалентно list[i]
в Java семантически. Разумеется, однако, что, как было сказано ранее, это связанные списки, поэтому получение i -го элемента требует O (i) вычислительных усилий. Хотя это может выглядеть как деталь, это может стать немного драматичным, если вы хотите получить объект с большим индексом. Кроме того, поскольку вызывается (!!)
, вы менее уверены в том, что есть такой элемент: у вас не так много гарантий, что список действительно достаточно длинный. Поэтому разумно использовать сопоставление образцов и искать умные способы использования структуры связанных списков.
Для примера для скалярного произведения, вы можете, например, первый образец использования сопоставления как:
dot (x:xs) (y:ys) = ...
и поэтому вы извлекли головыx
и y
из списков. И тогда вы можете умножить их и добавить их в скалярное произведение оставшейся части списка:
dot (x:xs) (y:ys) = x*y + dot xs ys
теперь вы только еще нужно определить базовый вариант (ы) как, например:
dot [] [] = 0.0
так положить все это вместе:
dot :: [Float] -> [Float] -> Float
dot [] [] = 0.0
dot (x:xs) (y:ys) = x*y + dot xs ys
Спасибо так много, что я даже не думаю, чтобы сделать базовый случай. Раньше я видел (x: xs), но точно не знал, что это значит. Это, наверное, самый информативный ответ, который я когда-либо получал в stackoverflow. Спасибо! – sbowde4
Обратите внимание, что это не относится к случаям, когда списки имеют разные длины. Вероятно, вам стоит подумать, как это сделать, даже если это не требуется для назначения. – Carl
@ Карл: Ну, я оставил это сознательно, так как продукт * dot * над двумя векторами разной длины довольно неопределен. Вы можете предположить, что «виртуальные хвосты» содержат нули, но, вероятно, что-то не так с кодом, который генерирует векторы. –