Question is in bold at the bottom.
LYAH gives this example of using the do
notation with the Writer
monad
import Control.Monad.Writer
logNumber :: Int -> Writer [String] Int
logNumber x = writer (x, ["number " ++ show x])
multWithLog :: Writer [String] Int
multWithLog = do
a <- logNumber 3
b <- logNumber 5
return (x*y)
where the definition can be re-written without the do
notation:
multWithLog = logNumber 3 >>= (\x ->
logNumber 5 >>= (\y ->
return (x*y)))
So far so good.
After that, the book introduces tell
, and edits the definition of multWithLog
like this:
multWithLog = do
a <- logNumber 3
b <- logNumber 5
tell ["something"]
return (x*y)
which again can be rewritten as:
multWithLog = logNumber 3 >>= (\x ->
logNumber 5 >>= (\y ->
tell ["something"] >>
return (x*y)))
Then the book makes the a point which appears unclear to me, if not inaccurate:
It's important that
return (a*b)
is the last line, because the result of the last line in ado
expression is the result of the whole do expression. Had we puttell
as the last line,()
would have been the result of thisdo
expression. We'd lose the result of the multiplication. However, the log would be the same.
Therefore, here my first doubt comes: if tell
results in ()
, then the code should not and does not even compile, as the ()
cannot match the expected type Int
, nor any other type other than ()
itself; so what is the author trying to tell us? To make this non-opinion-based, has something changed in Haskell, since the book was written, that made the above quoted statement unclear/inaccurate?
return (x*y)
line, then this will indeed not compile, since then()
would be the result. I do not really see what problem you face with the quoted paragraph? – FaeroeseWriter [String] ()
:). In that case the result will be()
but it will still write["something"]
to the log. – Faeroese