поведение foldl в бесконечных списках

Что я понял о foldl и foldr в списках:

Если мы вправо сбрасываем [0,1,2,3] с функцией s и начальным аккумулятором a , мы делаем это:

f 0 (f 1 (f 2 (f 3 a)))

Если мы оставили фолд [0,1,2,3] с функцией s и начальным аккумулятором a , мы делаем это:

f (f (f (f 0 a) 1) 2) 3)


Данный :

elem_r :: (Eq a) => a -> [a] -> Bool
elem_r y ys = foldr (\x acc -> if x == y then True else acc) False ys

и

elem_l :: (Eq a) => a -> [a] -> Bool
elem_l y ys = foldl (\acc x -> if x == y then True else acc) False ys

Мне кажется очевидным, что elem_r 3 [0..] вычислит то, что действительно должно, и вернет True, как только будет достигнуто значение 3.

f 0 (f 1 (f 2 (f 3 (...)))

В то время как elem_l 3 [0..] необходимо оценить все приложение вложенных функций, прежде чем возвращать результат.

f (f (f (f (f 0 3) 1) 2) 3) ...)


Теперь мой вопрос:

В конкретном случае elem_l 0 [0..] искомым элементом является первый элемент списка.

В этом выражении: f (f (f (f (f 0 0) 1) 2) 3) ...) Самая внутренняя функция (f 0 0) может быть немедленно оценена как «Истина». Почему Haskell продолжает оценивать остальные вложенные функции?


person espern    schedule 09.01.2015    source источник
comment
if x == y then True else acc мог бы быть немного аккуратнее, чем acc || x == y, имхо.   -  person Bartek Banachewicz    schedule 09.01.2015
comment
Рекомендуемая литература: haskell.org/haskellwiki/Foldr_Foldl_Foldl '   -  person jub0bs    schedule 09.01.2015
comment
@BartekBanachewicz, вы, несомненно, имели в виду x == y || acc.   -  person Will Ness    schedule 10.01.2015


Ответы (2)


Потому что f (f (f (f (f 0 0) 1) 2) 3) ...) не прав. Последняя скобка и первая f не совпадают, и исходный аргумент неверен. Это действительно так

(f ... (f (f (f (f False 0) 1) 2) 3) ...)

поэтому после того, как foldl завершит построение этого выражения (то есть никогда), мы должны пройти через бесконечное количество вложенных выражений, сначала оценивая их, прежде чем мы перейдем к самое внутреннее выражение, которое оценивается последним (потому что f останавливается на 0). Или в данном случае никогда.

И другой тест, ищущий 3, остановился бы раньше, на (f (f (f (f False 0) 1) 2) 3), потому что теперь f останавливается на 3; но все же ему придется сначала пройти через бесконечное количество вложенных выражений, после чего будет построено бесконечное вложенное выражение.

person Will Ness    schedule 09.01.2015

Даже если вы «немедленно» уменьшите f 0 0 до True, это не поможет. У вас все еще есть все окружающие вхождения f, которые нужно уменьшить ...

person kosmikus    schedule 09.01.2015