2013-12-16 3 views
4

Я пытаюсь написать функцию в Haskell, которая подсчитывает элементы в списке, удовлетворяющем предикату, и возвращает True, если число превышает некоторый порог. У меня есть реализация, которая выглядит следующим образом:Ленай оценка с предикатом

hitsThreshold :: Int -> (a -> Bool) -> [a] -> Bool 
hitsThreshold threshold test strs = 
    (length $ filter test strs) >= threshold 

Проблема заключается в том, что я хочу, чтобы это оценить лениво, так что он закончится, как только длина достигает порога. Например, я должен иметь возможность проходить в бесконечном списке, и он должен заканчиваться за конечное время (при условии, что порог в конечном итоге будет достигнут). Есть ли простой способ сделать это?

+4

Используйте 'takeWhile' вместо' filter'. Я все еще слишком плохо разбираюсь в Haskell, чтобы объяснить это правильно, но он должен работать. Или на самом деле просто 'take', потому что он получает первые элементы' n'. –

+1

было бы полезно посмотреть, как определяются 'length',' take' и 'filter' и думают о том, как они составляют под ленивой оценкой – jberryman

+1

[IOW] (http://stackoverflow.com/a/20622002/849891) 'hitsThreshold threshold test strs = (длина $ принимает порог $ filter test strs) == threshold'. –

ответ

10

Вот пример того, что вы хотите

length $ take 10 $ filter even [1..] 

[1 ..] бесконечна, так что если бы это было не лень, программа будет висеть.

Вы прокладываете трубку [1 ..] через фильтр even, затем закрываете номер на 10 .... Затем вы делаете что-то с этим списком. Вместо length вы можете проверить, достигли ли они порога, используя (>= 10) $ length).

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