Сопоставление с шаблоном Haskell на пустом множестве - PullRequest
17 голосов
/ 25 июля 2010

Я изменяю некоторый код на Haskell с использования списков на наборы. Я понимаю, что все необходимое, я думаю, но я не уверен, как сопоставить образец на наборах. Списки имеют этот приятный буквальный синтаксис, который, кажется, трудно эмулировать с помощью конструктора Set. Например, у меня может быть такой код:

foo [] = []
foo x = other_thing

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

Ответы [ 2 ]

33 голосов
/ 25 июля 2010

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

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

Потеря возможности сопоставления с шаблоном в абстрактном типе данных является неприятным побочным уроном, ну да ладно. Ваши варианты примерно:

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

Просмотр шаблонов позволит вам написать что-то похожее на это:

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

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

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

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

32 голосов
/ 25 июля 2010
import qualified Data.Set as Set

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