2017-02-05 3 views
2

Я невероятно новичок в Haskell, и у меня проблемы с домашней работой. Я не понимаю, как правильно взять массив и использовать данные в нем.Получение значений из массива

, например, в Java я бы что-то вроде

int[] arr = {...}; 
arr[0]; 
arr[1]; 

В моей проблемы Haskell у меня есть

dot :: [Float] -> [Float] -> Float 
-- enter code here 

Я не могу найти способ, чтобы использовать данные внутри массива с плавающей точкой. Пример моих профессоров для этой проблемы использует векторы, но мы должны использовать [Float]

Я не прошу кого-либо сделать проблему, просто объяснение того, как использовать массив.

ответ

11

Это технически говоря не массив, но (linked-) список. Это нечто другое. Список определяется как:

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 
+1

Спасибо так много, что я даже не думаю, чтобы сделать базовый случай. Раньше я видел (x: xs), но точно не знал, что это значит. Это, наверное, самый информативный ответ, который я когда-либо получал в stackoverflow. Спасибо! – sbowde4

+0

Обратите внимание, что это не относится к случаям, когда списки имеют разные длины. Вероятно, вам стоит подумать, как это сделать, даже если это не требуется для назначения. – Carl

+2

@ Карл: Ну, я оставил это сознательно, так как продукт * dot * над двумя векторами разной длины довольно неопределен. Вы можете предположить, что «виртуальные хвосты» содержат нули, но, вероятно, что-то не так с кодом, который генерирует векторы. –