Как сопоставить шаблон с пустым вектором в Haskell?
Скажем, я хочу реализовать функцию длины для списков, используя сопоставление с образцом, тогда я мог бы сделать что-то вроде этого:
length' :: (Num b) => [a] -> b
length' [] = 0
length' (_:xs) = 1 + length' xs
Могу ли я сделать что-то подобное с Vector
s?
1 ответ
vector
библиотека различная Vector
типы - это непрозрачные типы, которые не предоставляют своих конструкторов данных, и поэтому вы не можете сопоставить их с шаблоном.
Есть способы обойти это, как ViewPatterns
(как упоминает комментарий пользователя user2407038), но вы определенно не хотите использовать их с векторами, потому что вы, вероятно, отбросите преимущество использования векторов.
Изюминка vector
Библиотека заключается в том, что она реализована на основе двух концепций:
- Векторы материализуются как непрерывные массивы памяти фиксированного размера, которые обеспечивают гораздо лучшую локальность памяти, чем списки или деревья с одной связью;
- Большое количество векторных операций реализовано в виде плавких потоков, чьи операции компилируются в циклы, которые не выделяют память для промежуточных векторов.
(1) означает, что вектор не имеет естественных "головы" и "хвоста", как списки - списки - это буквально пара головы и хвоста. Если бы вы использовали какой-либо шаблон представления для наложения структуры "голова + хвост" поверх вектора, вы бы эффективно создали односвязный список элементов вектора, который, вероятно, инициировал бы выделение памяти для каждого узла тип просмотра.
И если вы использовали ViewPatterns
чтобы рассматривать вектор как фактически единый связанный список, почему бы просто не преобразовать вектор в список?
В любом случае, из-за проектных точек, упомянутых выше, с vector
Вы действительно хотите как можно больше придерживаться операций, предоставляемых самой библиотекой, потому что они будут использовать возможности библиотеки.
Я подозреваю, что есть хороший шанс, что тестирование размера вектора может быть неоптимальной идеей во многих контекстах. Например, в таком коде:
example :: Vector something -> Vector somethingElse
example as
| Vector.null as = ...
| otherwise = ...
... Я ожидаю (но не проверил!), Что это заставит вектор as
материализоваться так, чтобы мы могли проверить, является ли он пустым или нет, где, если тест может быть удален или перемещен куда-то еще, возможно, что операции в бите "..." могут быть объединены с контекстом, в котором example
используется.