Как сопоставить шаблон с пустым вектором в Haskell?

Скажем, я хочу реализовать функцию длины для списков, используя сопоставление с образцом, тогда я мог бы сделать что-то вроде этого:

length' :: (Num b) => [a] -> b  
length' [] = 0  
length' (_:xs) = 1 + length' xs  

Могу ли я сделать что-то подобное с Vectors?

1 ответ

Решение

vector библиотека различная Vector типы - это непрозрачные типы, которые не предоставляют своих конструкторов данных, и поэтому вы не можете сопоставить их с шаблоном.

Есть способы обойти это, как ViewPatterns (как упоминает комментарий пользователя user2407038), но вы определенно не хотите использовать их с векторами, потому что вы, вероятно, отбросите преимущество использования векторов.

Изюминка vector Библиотека заключается в том, что она реализована на основе двух концепций:

  1. Векторы материализуются как непрерывные массивы памяти фиксированного размера, которые обеспечивают гораздо лучшую локальность памяти, чем списки или деревья с одной связью;
  2. Большое количество векторных операций реализовано в виде плавких потоков, чьи операции компилируются в циклы, которые не выделяют память для промежуточных векторов.

(1) означает, что вектор не имеет естественных "головы" и "хвоста", как списки - списки - это буквально пара головы и хвоста. Если бы вы использовали какой-либо шаблон представления для наложения структуры "голова + хвост" поверх вектора, вы бы эффективно создали односвязный список элементов вектора, который, вероятно, инициировал бы выделение памяти для каждого узла тип просмотра.

И если вы использовали ViewPatterns чтобы рассматривать вектор как фактически единый связанный список, почему бы просто не преобразовать вектор в список?

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

Я подозреваю, что есть хороший шанс, что тестирование размера вектора может быть неоптимальной идеей во многих контекстах. Например, в таком коде:

example :: Vector something -> Vector somethingElse
example as 
  | Vector.null as = ...
  | otherwise      = ...

... Я ожидаю (но не проверил!), Что это заставит вектор as материализоваться так, чтобы мы могли проверить, является ли он пустым или нет, где, если тест может быть удален или перемещен куда-то еще, возможно, что операции в бите "..." могут быть объединены с контекстом, в котором example используется.

Другие вопросы по тегам