I am learning about the Writer Monad on the book Learn You A Haskell.
this is the piece of code:
import Control.Monad.Writer
logNumber :: Int -> Writer [String] Int
logNumber num = writer (num, ["Got number: " ++ show num])
multWithLog :: Writer [String] Int
multWithLog = do
a <- logNumber 3
b <- logNumber 5
return (a * b)
When running multWithLog
, this is the result:
*Main> runWriter multWithLog
(15,["Got number: 3","Got number: 5"])
On this lines:
a <- logNumber 3
b <- logNumber 5
It is easy to see that a = 3
and b = 5
, since both of them are being multiplied on the return
function.
What I don't understand is why those values are 3
and 5
. Shouldn't a
and b
be the values that contain inside the Writer
Monad? In this case tuples?
For example, with this was with the Maybe
Monad, a
and b
would be 3
and 5
:
do
a <- Just 3
b <- Just 5
return (a * b)
In this case it makes sense to me, since a
and b
receive the content inside Just
. But with the initial example, a
and b
only receive part of the value.
It is easy to see that a = 3 and b = 5, since both of them are being multiplied on the return function. What I don't understand is why those values are 3 and 5. Shouldn't a and b be the values that contain inside the Writer Monad? In this case tuples?
No. I think the simplest way to answer this is to just implement the Writer
type and study its Monad
class instance:
newtype Writer w a = Writer { runWriter :: (a, w) }
instance Functor (Writer w) where
fmap f (Writer (a, w)) = Writer (f a, w)
instance Monoid w => Applicative (Writer w) where
pure a = Writer (a, mempty)
Writer (f, w) <*> Writer (a, w') = Writer (f a, w <> w')
instance Monoid w => Monad (Writer w) where
return = pure
Writer (a, w) >>= f = let (b, w') = runWriter (f a)
in Writer (b, w <> w')
tell :: w -> Writer w ()
tell w = Writer ((), w)
As you can see in the instance method for >>=
, the function f
is applied to the a
value, not the whole tuple. The syntax a <- logNumber 3
is desugared using >>=
, so the value that's bound to a
will be the first element of the tuple that Writer
wraps around.