2017-01-29 4 views
0

Я пытаюсь создать отфильтрованное декартово произведение из определенного списка списков. Наивное решение заключается в следующем:отфильтрованный список декартовых продуктов без промежуточного списка

import Data.Traversable (sequence) 

predicate :: [T] -> Bool 
predicate = ... 

filteredCartesianProduct :: [[T]] -> [[T]] 
filteredCartesianProduct = filter predicate . sequence 

Проходит достаточно мощный, чтобы сделать это без создания промежуточного списка? Есть ли идиоматический способ сделать это?

+1

Предполагая, что подпись вашей функции «предикат» верна, ваша реализация 'filterPowerSet' неверна. Почему вы создаете «фильтр-предикат» с 'sequence'? Это не проверяет тип. Разве ваша реализация не должна быть «filterPowerSet = фильтр-предикат»? – liminalisht

+1

Объявленный тип подразумевает, что вы уже получаете (или, по крайней мере, ожидаете) набор полномочий, а не набор, в качестве аргумента. – chepner

+0

Я получаю список списков, например [[1,2], [3,4,5]], последовательность производит следующее: [[1,3], [1,4], [1,5], [2,3], [2,4], [2,5]]. – lanskey

ответ

1

traverse здесь кодирует рисунок, который predicate имеет форму all foo для некоторых foo. Затем filteredCartesianProduct - traverse (filter foo).

Если predicate говорит да для каждого префикса любого списка, на котором он говорит, что да, у вас есть шаблон с возвратами:

filteredCartesianProduct = foldlM (\accum factor -> [new | x <- factor, let new = accum ++ [x], predicate new]) [] 

Интересно, как избавиться от запаха ++ [_].

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