Warning: before reading the text below, you should already have an idea of what monads are. If this is not the case, then read
this post before!
Before us function
half
:

And we can apply it several times:
half . half $ 8 => 2
')
Everything works as expected. But you decided that it would be nice to have a log of what is happening with this function:

half x = (x `div` 2, " " ++ (show x) ++ "!")
Well, great. But what if you now want to apply
half
few times?
half . half $ 8
Here is what we
would like to happen:
Spoiler : not automatically done. We'll have to paint everything handles:
finalValue = (val2, log1 ++ log2) where (val1, log1) = half 8 (val2, log2) = half val1
Ugh! This is not a drop like laconic
half . half $ 8
And what if you still have functions that have a log? This scheme suggests itself: for each function that returns, together with the value of the log, we would like to combine these logs. This is a side effect, and no one is as strong in side effects as monads!
Monad Writer
The monad Writer appears on the white horseMonad Writer is a cool personality. “Don't worry, man, I'll process your logs,” she says. - “Go back to your clean code and squeeze the maximum for anything from Zeppelin!”
Each Writer instance has a log and a return value:

data Writer wa = Writer { runWriter :: (a, w) }
Writer allows us to write code like
half 8 >>= half
Well, or you can use the
<=<
function, which is the composition of functions for monads, to get:
half <=< half $ 8
which is damn close to
half . half $ 8
half . half $ 8
. Cool!
You can use
tell
to write something to the log. And
return
will pass this value to Writer. Here is our updated
half
function:
half :: Int -> Writer String Int half x = do tell ("I just halved " ++ (show x) ++ "!") return (x `div` 2)
It returns
Writer
:

And we can use
runWriter
to extract the value from it:

runWriter $ half 8 => (4, "I just halved 8!")
But the coolest thing is that now we can link the
half
calls to a chain using
>>=
:
runWriter $ half 8 >>= half => (2, "I just halved 8!I just halved 4!")
Here is what happens:

Magically
>>=
knows how to combine the two Writers, so we don’t need to write any tedious code ourselves! Here is the full definition
>>=
:

We wrote the exact same template code earlier, but now we have assumed this responsibility
>>=
. Cool We also use the
return
function, which takes a value and places it in the monad:

return val = Writer (val, "")
(
Note : this definition is
almost correct. In fact, the
Writer
monad allows us to use any
Monoid
as a log, not just strings. I simplified it slightly.)
Thank you, monad Writer!
Monad Reader
Suppose you want to pass some settings to a variety of functions. Just use the Reader monad:

It allows you to transfer your value to all functions, hiding the transmission mechanism itself behind the scenes. For example:
greeter :: Reader String String greeter = do name <- ask return ("hello, " ++ name ++ "!")
greeter
returns the reader monad:

Here is its definition:
data Reader ra = Reader { runReader :: r -> a }
Reader has always been a turncoat. Dark horse. Reader is different because it allows us to process a function, which is confusing when considering it. But you and I understand that we can use
runReader
to extract this function:

And we can transfer a certain state to this function, which is then used in
greeter
:

runReader greeter $ "adit" => "hello, adit!"
this way, when you use
>>=
, you should get a Reader back. When you pass a state to it, it will be transferred to all functions contained in this monad.

m >>= k = Reader $ \r -> runReader (k (runReader mr)) r
Reader has always been somewhat comprehensive. This is generally his best quality.
return
puts the value in the
Reader
:

return a = Reader $ \_ -> a
And, finally,
ask
gives you back the state you passed:
ask = Reader $ \x -> x
Want to spend more time with Reader? Cut punk rock and take a look at
a longer example .
Monad State
The Monad State is the more impressionable best friend of the Reader monad:

It is exactly the same as the Monad Reader, but with its help you can not only read but also write!
Here is the definition of
State
:
State sa = State { runState :: s -> (a, s) }

You can get a state with
get
or change it with
put
. Here is an example:
greeter :: State String String greeter = do name <- get put "tintin" return ("hello, " ++ name ++ "!") runState greeter $ "adit" => ("hello, adit!", "tintin")
Nicely! If the Reader was with the character “you-me-not-change”, then State, on the contrary, tends to relations and is ready to change itself.
The definition of a
State
monad looks very similar to the definition of a
Reader
monad:
return
:

return a = State $ \s -> (a, s)
>>=
:

m >>= k = State $ \s -> let (a, s') = runState ms in runState (ka) s'
Conclusion

Writer. Reader. State. Today you have added three powerful weapons to your Haskell arsenal. Use them wisely.
From the translator: I will be infinitely grateful for any comments in PM that will help improve the quality of this translation.