Вы забываете, что оператор >>=
возвращает не просто f (h w) w
, а \w -> f (h w) w
. То есть он возвращает функцию, а не число.
При неправильной подстановке вы потеряли самый внешний параметр w
, поэтому неудивительно, что он остается свободным в вашем конечном выражении.
сделать это правильно, вы должны полностью заменить тела функций для их вызовов, не отбрасывая вещи.
Если вы подставите самое внешнее >>=
, вы получите:
(*2) >>= (\a -> ...)
==
\w -> (\a -> ...) (w*2) w
Тогда, если Вы заменяете самый внутренний >>=
, вы получаете:
\a -> (+10) >>= (\b -> return (a+b))
==
\a -> \w1 -> (\b -> return (a+b)) (w1 + 10) w1
Обратите внимание, что я использую w1
вместо w
. Это сделано для того, чтобы избежать конфликтов имен позже, когда я объединю подстановки, потому что эти два w
взяты из двух разных лямбда-абстракций, поэтому они являются разными переменными.
Наконец, подставим return
:
return (a+b)
==
\_ -> a+b
Теперь вставьте эту последнюю замену в предыдущую:
\a -> (+10) >>= (\b -> return (a+b))
==
\a -> \w1 -> (\b -> return (a+b)) (w1 + 10) w1
==
\a -> \w1 -> (\b -> \_ -> a+b) (w1 + 10) w1
И, наконец, вставьте это в самую первую замену:
(*2) >>= (\a -> ...)
==
\w -> (\a -> ...) (w*2) w
==
\w -> (\a -> \w1 -> (\b -> \_ -> a+b) (w1 + 10) w1) (w*2) w
И теперь, когда все замены конкурируют, мы можем уменьшить. Начните с применения самой внутренней лямбды \b -> ...
:
\w -> (\a -> \w1 -> (\_ -> a+w1+10) w1) (w*2) w
Теперь примените новую внутреннюю лямбду \_ -> ...
:
\w -> (\a -> \w1 -> a+w1+10) (w*2) w
Теперь примените \a -> ...
:
\w -> (\w1 -> w*2+w1+10) w
И наконец примените единственную оставшуюся лямбду \w1 -> ...
:
\w -> w*2+w+10
И вуаля! Вся функция уменьшается до \w -> (w*2) + (w+10)
, как и ожидалось.