Сравнение может выполняться до полного расчета LHS. Как только filter создал один элемент, /= может сделать вывод, что список не может быть равен [], и немедленно вернуть True.
/= в списках реализовано примерно так:
(/=) :: Eq a => [a] -> [a] -> Bool
[] /= [] = False
[] /= (y:ys) = True
(x:xs) /= [] = True
(x:xs) /= (y:ys) = (x /= y) || (xs /= ys)
Поскольку Haskell ленив, мы будем оценивать аргументы ровно столько, сколько необходимо, чтобы выбрать, какую правую часть мы будем использовать. Оценка вашего примера выглядит примерно так:
filter (== True) (map (\x -> True) [1..]) /= []
==> (True : (filter (== True) (map (\x -> True) [2..]))) /= []
==> True
Как только мы узнаем, что первый аргумент /= равен (1 : something), он соответствует третьему уравнению для /= в приведенном выше коде, поэтому мы можем вернуть True.
Однако, если вы попробуете thereExists (\x -> False) [1..], он действительно не завершится, потому что в этом случае filter никогда не продвинется к созданию конструктора, с которым мы можем сопоставляться.
filter (== True) (map (\x -> False) [1..]) /= []
==> filter (== True) (map (\x -> False) [2..]) /= []
==> filter (== True) (map (\x -> False) [3..]) /= []
...
и так бесконечно.
В заключение, thereExists в бесконечном списке может вернуть True за конечное время, но никогда False.
person
hammar
schedule
29.10.2012
thereExistsесть в стандартной библиотеке, за исключением того, что он называетсяany. - person hammar   schedule 30.10.2012