The state and reader monad both depend on the value of whatever state we're interested in. We need to be able to access it otherwise how could we write something like
foo = do
i <- get
return $ if i == 1 then 2 else 3
So our state monad naturally looks like something that takes in a state, does stuff, and produces a new one.
Likewise with the reader monad, we take in some state, magic, and produce an output (but no new state since it's Reader s a <=> s -> a
.
Now this is very different than the writer monad. In the writer, we don't care about what's been stuck in the state previously, all we want to do is take our current state, and jam some more stuff in there. Because our state is a monoid, we have a guaranteed start state mempty
and a way to jam stuff in mappend
. This means that we can "run" each computation in an empty context so to speak and just fuse the outputs together and get identical results.
Ok, now there's about a few questions so I'll go one at a time
If the writer monad had access to the previously written results, then it's going to look like
s -> (s, a)
which is the state monad :) So yes, whatever you could do with the state monad could be done with this augmented writer.In fact both the
StateT
andWriterT
monads haveMonadPlus
instances so I'm not sure what you're getting at here..Since there isn't an arbitrary function
m a -> a
, we need some way to unwrap a computation to view the results ala>>=
, and sincereturn :: a -> m a
makes it trivial to go the other way, it's more general to go from plain to monadic value. Otherwise we'd just have these uselessIO String
,STM Int
and whatnot that we couldn't depend on for the rest of our computation sincefmap
won't let us hoist in more side effects.