Given addStuff
addStuff :: Int -> Int
addStuff = do
a<-(*2)
b<-(+10)
return (a+b)
the definition desugars into
addStuff =
(* 2) >>= \a ->
(+ 10) >>= \b ->
return (a + b)
Hovering over the >>=
in fpcomplete online editor shows
:: Monad m => forall a b.
(m a ) -> (a -> m b ) -> (m b )
:: (Int -> a ) -> (a -> Int -> b ) -> (Int -> b )
:: (Int -> Int) -> (Int -> Int -> Int) -> (Int -> Int)
That leads us to believe we use a Monad instance for functions. Indeed if we look at the source code, we see
instance Monad ((->) r) where
return = const
f >>= k = \ r -> k (f r) r
Using this newly obtained information we can evaluate the addStuff
function ourselves.
Given the initial expression
(* 2) >>= ( \a -> (+10) >>= \b -> return (a + b) )
we substitute using the >>=
definition, giving us (in the following {}
, []
, ()
just illustrate different depth of ()
)
\r1 -> {\a -> (+10) >>= \b -> return (a + b)} {(* 2) r1} r1
simplify the second-to-last term inside the outermost lambda
\r1 -> {\a -> (+10) >>= \b -> return (a + b)} {r1 * 2} r1
apply {r1 * 2}
to {\a -> ...}
\r1 -> {(+10) >>= \b -> return ((r1 * 2) + b)} r1
substitute remaining >>=
with its definition again
\r1 -> {\r2 -> [\b -> return (r1 * 2 + b)] [(+10) r2] r2} r1
simplify second-to-last term inside inner lambda
\r1 -> {\r2 -> [\b -> return (r1 * 2 + b)] [r2 + 10] r2} r1
apply [r2 + 10]
to {\b -> ...}
\r1 -> {\r2 -> [return (r1 * 2 + (r2 + 10))] r2} r1
apply r1
to {\r2 -> ...}
\r1 -> {return (r1 * 2 + r1 + 10) r1}
substitute return
with its definition
\r1 -> {const (r1 * 2 + r1 + 10) r1}
evaluate const x _ = x
\r1 -> {r1 * 2 + r1 + 10}
prettify
\x -> 3 * x + 10
finally we get
addStuff :: Int -> Int
addStuff = (+ 10) . (* 3)