Давайте сначала десугар блок do
[отчет Haskell'10] :
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
эквивалентен:
addStuff = (*2) >>= \a -> ((+10) >>= \b -> return (a + b))
Внутреннее выражение связывания ((+10) >>= \b -> return (a + b)
), таким образом, можно преобразовать с определением связывания в:
\w -> (\b -> return (a + b)) ((+10) w) w
, и если мы заменим return
на const
, мы получим:
\w -> (const . (a+)) ((+10) w) w
Таким образом, у нас есть функция, которая принимает в качестве ввода w
, а затем вызывает const . (a+)
для (w+10)
и w
, поэтому она игнорирует последние w
.Семантически это эквивалентно:
(a+) . (+10)
Так что теперь наш addStuf
эквивалентен:
addStuff = (*2) >>= \a -> ((a+) . (+10))
, и если мы теперь снова используем определение для оператора связывания, мы видим:
\w -> (\a -> ((a+) . (+10))) ((*2) w) w
или короче:
\w -> (\a -> ((a+) . (+10))) (w*2) w
Теперь мы можем заменить a
на (w*2)
и получить:
\w -> ((w*2)+) . (+10)) w
Так что наш addStuf
равенэквивалентно:
addStuff w = (w*2) + (w+10)
или более простым:
addStuff w = 3*w + 10