Intuition for “run” function of monads

  • A+

I'm learning about monads in Haskell, I understood why they are useful, I understood in general what bind, join, return do.

I also looked at basic usage examples for the basic reader / writer / state / list / maybe monads.

Still, being a beginner, I still don't feel I have a grip on what the "run" function (e.g. runState, runReader, runWriter) mean in general. It does not seem to have a generic signature like the above functions, and I don't get it if it's definable / makes sense for all monads.


The run function for most monads is actually just an artifact of how the monad is internally represented; For example, the Reader monad could theoretically be represented as just

type Reader r a = r -> a 

State as

type State s a = s -> (s, a) 

and so on. However, if we did that then we couldn't provide different typeclass (including Monad) implementations for Reader and State as they'd both just be represented by (->).

-- that is, if we wrote

instance Functor (Reader r)   -- .... 


instance Functor (State s)   -- ... 

our compiler would complain we're trying to give two different Functor implementations for (->) a.

So instead of type we just more or less write the same thing with newtype, e.g.

newtype Reader r a = Reader { runReader :: r -> a } 


newtype State s a = State { runState :: s -> (s, a)} 

As you can see, the run functions don't actually do anything here, they just "unwrap" the newtype so we can get the underlying value.

(actual implementations may involve monad transformers and therefore look a bit more complicated, but they're essentially still doing the same thing).


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: