2015-05-03 9 views
1

Я столкнулся с проблемой. В чем разница между этими двумя функциями:Функция Haskell foldl ( x y -> x * 2 + y * 2) 0 поведение

foldl (\x y -> x*2 + y*2) 0 [1,2,3] = 22 
foldr (\x y -> x*2 + y*2) 0 [1,2,3] = 34 

foldl (\x y -> x*2 + y*2) 0 [1,2,3] ⇒ f(f(f(0,1),2),3) 
foldr (\x y -> x*2 + y*2) 0 [1,2,3] ⇒ f(3,f(2, f(1,0))) 

, где f = \x y -> x*2 + y*2.

Я понимаю результат foldl:

x = f(0,1) = 2 
y = f(x,2) = 8 
z = f(y,3) = 22 

Но почему foldr сумма после результата каждого шага?

2 + 8 + 22 = 34 
+1

Если вы пытались получить сумму квадратов, то вы хотите: 'foldl» (\ х -> х + у^2) 0 ' –

+1

отметить также, что это правило, рекомендуется всегда использовать строгую версию 'foldl' -' foldl'', поскольку он не вызывает утечки памяти. – Mark

+0

@Mark спасибо за правильное редактирование –

ответ

4

У вас есть оценка foldr назад. Он должен выглядеть следующим образом:

foldr f 0 [1,2,3] == f 1 (f 2 (f 3 0)) 

Для контраста, то foldl оценка (что является правильным в вашем вопросе) выглядит

foldl f 0 [1,2,3] == f (f (f 0 1) 2) 3 

Если вы чувствуете себя комфортно думать о списке [1,2,3] как то же самое, 1:2:3:[], эта схема foldr может помочь:

foldr diagram

+0

спасибо за помощь, после ответа я начал понимать эти диаграммы. Большое спасибо! –

2

Ваше определение foldr немного не работает. Вместо f(3,f(2, f(1,0))) оно должно быть f(1,f(2, f(3,0))).

foldl f z [1,2,3] = ((0 `f` 1) `f` 2) `f` 3 
        = ((0*2 + 1*2) `f` 2) `f` 3 
        = (2 `f` 2) `f` 3 
        = (2*2 + 2*2) `f` 3 
        = 8 `f` 3 
        = 8*2 + 3*2 
        = 22 

foldr f z [1,2,3] = 1 `f` (2 `f` (3 `f` 0)) 
        = 1 `f` (2 `f` (3*2 + 0*2)) 
        = 1 `f` (2 `f` 6) 
        = 1 `f` (2*2 + 6*2) 
        = 1 `f` 16 
        = 1*2 + 16*2 
        = 34 
+0

спасибо за объяснение –

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