2010-07-25 4 views
16

Я меняю код Haskell на использование списков в наборах. Я понимаю все, что нужно, я думаю, но я не уверен, как сопоставить шаблон по наборам. В списках есть такой хороший литеральный синтаксис, который кажется сложным эмулировать с помощью конструктора Set. Например, я мог бы иметь некоторый код, как это:Haskell Pattern Matching on the Empty Set

foo [] = [] 
foo x = other_thing 

Как я могу написать этот код, чтобы он использует наборы вместо списков?

ответ

30

Ну, вы не можете.

Set является абстрактным типа данных[0], что намеренно скрывает свое внутреннее представление, в первую очередь поддерживать инварианты структуры данных, которые не могут быть статический принудительной системой типа (в частности, стандартная библиотека Data.Set.Set - двоичное дерево поиска).

Потеря способности сопоставления рисунка по абстрактному типу данных - неприятный бит сопутствующего урона, но хорошо. Ваши варианты примерно:

  • Использование булевых предикатов и охранников, например. null, как и в ответе тринита.
  • Преобразуйте Set в список. В большинстве случаев это глупо, но если вы хотите все равно итерации по набору, это работает достаточно хорошо.
  • Включить GHC's ViewPatterns extension, который обеспечивает синтаксический сахар для использования функций доступа, где обычно идет совпадение с шаблоном.
  • Избегайте делать эти проверки в первую очередь - если у вас есть Set, относитесь к нему как к , установленному, и работайте с ним в целом для картирования, фильтрации и т. Д. Не всегда возможно, но может привести для более чистого кода с меньшим количеством явных условностей/итераций.

Просмотр моделей позволит вам написать что-то, что выглядит следующим образом:

foo (setView -> EmptySet) = [] 
foo (setView -> NonEmpty set) = other_thing 

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

Для избежания явных проверок, помимо хорошо известный набор операции, такие как union и intersection, рассмотреть возможность использования из filter, partition, map, и fold функции в Data.Set.

[0]: См. this paper (предупреждение: PDF) для определения термина, поскольку я его использую.

+0

+1 для ссылки ViewPatterns! – ShiDoiSi

29
import qualified Data.Set as Set 

foo set 
    | Set.null set = bar 
    | otherwise = baz 
+1

+1 для простого ответа –

+7

@simonjpascoe: Подождите, мы можем дать * простые ответы? И здесь все это время я думал, что есть минимум из трех абзацев ... –