# Understanding do notation with Monads in Plutus Pioneer Week 04

I have a question regarding a block of code from th Week04 Plutus Pioneer Program. The block is in Writer.hs

``````foo'' :: Writer Int -> Writer Int -> Writer Int -> Writer Int
foo'' x y z = do
s <- threeInts x y z
tell ["sum: " ++ show s]
return s
``````

For reference,

``````threeInts :: Monad m => m Int -> m Int -> m Int -> m Int
threeInts mx my mz =
mx >>= \k ->
my >>= \l ->
mz >>= \m ->
let s = k + l + m in return s

tell :: [String] -> Writer ()
tell = Writer ()

return a = Writer a []

number :: Int -> Writer Int
number n = Writer n \$ ["number: " ++ show n]
``````

Why does

``````foo'' (number 2) (number 3) (number 4)
``````

return

``````Writer 9 ["number: 2","number: 3","number: 4","sum: 9"]
``````

and not

``````Writer 9 []
``````

Obviously there are holes in my understanding, but I read the `do` block as follows:

• The result of `threeInts x y z` is `Writer 9 ["number: 2","number: 3","number: 4"]`
• 9 is extracted from this to the definition `s`
• `tell ["sum: " ++ show s]` results in `Writer () ["sum: 9"]`
• `return s` results in `Writer 9 []`

I know that `return` in Haskell is not the same as it is in an imperative language, but I'm failing miserably to grok how to read this block effectively. The lambda version producing the same result is more explicit and makes sense to me.

``````bindWriter :: Writer a -> (a -> Writer b) -> Writer b
bindWriter (Writer a xs) f =
let
Writer b ys = f a
in
Writer b \$ xs ++ ys

foo' :: Writer Int -> Writer Int -> Writer Int -> Writer Int
foo' x y z = x `bindWriter` \k ->
y `bindWriter` \l ->
z `bindWriter` \m ->
let s = k + l + m
in tell ["sum: " ++ show s] `bindWriter` \_ ->
Writer s []
``````

I read this backwards where (for my concrete example) `Writer 9 []` is bound/combined with `Writer () ["sum: 9"]` which is then bound/combined with `Writer 4 ["number: 4"]`, `Writer 3 ["number: 3"]` and `Writer 2 ["number: 2"]` where the Int values are discarded in the bind process and the "logs" are concatenated.

There is something implicit in the `do` notation that I'm overlooking or not reading correctly. Any help appreciated.

The 'secret' is in the `bindWriter` function that drive the `Writer` monad.

``````instance Monad Writer where
return a = Writer a []
(>>=) = bindWriter
``````

It is the `bindWriter` function that aggregates the string list of the `Writer`s and this happens as part of the execution of the `do` block which is a list of monadic statements.

For instance, comment out the `tell` line and the `do` block in `foo''` returns

``````Writer 9 ["number: 2","number: 3","number: 4"]
``````

Rewriting the `do` block to

``````foo'' x y z = do
threeInts x y z
``````

returns the same result. Without return the `do` block returns the result of the last line (and the compiler complains when it isn't of the right type).

Adding a `Writer` line returns the `Int` from the `Writer`, but the full list of strings:

``````foo'' x y z = do
threeInts x y z
``````Writer 0 ["number: 1","number: 2","number: 3","adding 0"]
The `tell` function causes a string list to be added ignoring the `Int` part. The `threeInts` result needs to be captured because it contains the `Int` result that needs to be returned (and the `tell` line needs it for the text line).