2015-08-06 2 views
5

Есть ли какая-либо возможность, например расширение языка, использовать синтаксис синтаксиса понятий списка для Data.Set наборов?Haskell Set Comprehensions

Пример:

f :: Set a -> Set b -> Set (a,b) 
f xs ys = [(x,y) | x <- xs , y <- ys] -- this is the set comprehension 

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

И да, я знаю MonadComprehensions для использования синтаксиса список-аккомпанемента с любым типом Monad/MonadPlus но AFAIK множеств не может быть даже монады из-за Ord ограничения в большинстве функций.

+1

«множества - это математическая структура, которая вдохновила на понимание списков». Но Data.Set не является такой структурой 'из-за ограничения Ord'. –

ответ

6

В теории, нет

Там нет языковых расширений, которые позволяют для «установить постижения.»

Различия между Set и List являются:

  1. Set является неупорядоченным, а List заказана
  2. элементы Set являются уникальными в то время как List могут иметь повторяющиеся элементы
  3. тип Set является примером Ord, в то время как у List нет ограничений по типу.

Вы можете видеть, что все возможные Set s являются строгим подмножеством всех возможных List. Это означает, что мы можем достичь «установленного понимания», просто используем понимание списка и преобразовывая его в Set. Ленивая оценка будет часто сделать "set generation" эффективной исходя из самых конечных списков. Однако перечни, приводящие к спискам бесконечных, вряд ли приведут к эффективному «установлению понимания».

Пример:

import Data.Set 

set :: Ord a => Set a 
set = fromList [x * y | x <- [1..10], y <- [1..10]] 

В практике, да

Используя set-monad пакет, вы можете определить Set как экземпляр Monad и с помощью расширения MonadComprehensions языка вы можете получить «набор понимание».

Пример:

{-# LANGUAGE MonadComprehensions #-} 
import Data.Set.Monad 

set1 :: Set (Int,Int) 
set1 = do 
     a <- fromList [1 .. 4] 
     b <- fromList [1 .. 4] 
     return (a,b) 

-- Look a "set comprehension" 
set2 :: Set (Int,Int) 
set2 = [ (a,b) | (a,b) <- set1, even a, even b ] 

Используйте тот метод, который имеет наибольший смысл для вашего проекта. Перед тем как принять решение!

+1

Err ... как бы ленивая оценка сделала эффективное поколение?Вы должны оценить весь список, чтобы создать набор. Кажется, ленивая оценка вообще ничего не делает. – Cubic

+1

@Cubic Вы не будете генерировать весь список и затем сгенерировать весь набор. Операция будет плавкой из-за ленивой оценки, поэтому, если я создаю большой список дубликатов одного элемента, я не буду нести накладные расходы памяти, так как набор будет лениво рисовать из списка и создавать одноэлементный набор. –

+1

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

Смежные вопросы