Я изменяю некоторый код Haskell от использования списков к наборам. Я понимаю все требуемое, я думаю, но я не уверен, как скопировать соответствие на наборах. Списки имеют этот хороший литеральный синтаксис, который кажется твердым эмулировать с конструктором Set. Например, у меня мог бы быть некоторый код как это:
foo [] = []
foo x = other_thing
Как я могу написать этот код, таким образом, он использует Наборы вместо списков?
Ну, не можете.
Набор
- это абстрактный тип данных [0] , который намеренно скрывает свое внутреннее представление, в первую очередь для поддержания инвариантов структуры данных, которые не могут быть статически принудительно реализованы системой типов (в частности, стандартным библиотека Data.Set.Set
- дерево двоичного поиска).
Потеря способности сопоставления с образцом в абстрактном типе данных является неприятным сопутствующим ущербом, ну да ладно. Возможны следующие варианты:
null
, как в ответе тринитиса. набор
в список. В большинстве случаев это глупо, но если вы все равно хотите перебирать набор, это работает достаточно хорошо. ViewPatterns
расширение , которое обеспечивает синтаксический сахар для использования функций доступа там, где обычно происходит сопоставление с образцом. Набор
, относитесь к нему как к набору и работайте с ним в целом для сопоставления, фильтрации и т. д. Не всегда возможно, но может привести к более чистому коду с меньшим количеством явных условий / итераций. Шаблоны просмотра позволят вам написать что-то вроде этого:
foo (setView -> EmptySet) = []
foo (setView -> NonEmpty set) = other_thing
... где setView
- это функция, которую вы пишете.Здесь не очень много выигрыша, но может быть хорошо для более сложных псевдошаблонов
, чтобы избежать явных проверок, помимо хорошо известных операций над множествами, таких как union
и пересечение
, рассмотрите возможность использования функций filter
, partition
, map
и fold
в Data.Set
.
[0]: См. этот документ (предупреждение: PDF) для определения термина в том виде, в каком я его использую.
import qualified Data.Set as Set
foo set
| Set.null set = bar
| otherwise = baz