What is the difference between different orderings of the same monad transformers?

前端 未结 5 1411
你的背包
你的背包 2021-01-31 18:09

I am attempting to define an API to express a particular type of procedure in my program.

newtype Procedure a = { runProcedure :: ? }

There is

5条回答
  •  时光说笑
    2021-01-31 18:38

    To complement the other answers, I'd like to describe how to figure this out in the general case. That is, given two transformers, what are the semantics of their two combinations?

    I had a lot of trouble with this question when I was starting to use monad transformers in a parsing project last week. My approach was to create a table of transformed types that I consult whenever I'm unsure. Here's how I did it:

    Step 1: create a table of the basic monad types and their corresponding transformers types:

    transformer           type                  base type (+ parameter order)
    
    ---------------------------------------------------------------
    
    MaybeT   m a        m (Maybe a)            b.    Maybe b
    
    StateT s m a        s -> m (a, s)          t b.  t -> (b, t)
    
    ListT    m a        m [a]                  b.    [] b
    
    ErrorT e m a        m (Either e a)         f b.  Either f b
    
    ... etc. ...
    

    Step 2: apply each monad transformer to each of the base monads, substituting in for the m type parameter:

    inner         outer         combined type
    
    Maybe         MaybeT        Maybe (Maybe a)
    Maybe         StateT        s -> Maybe (a, s)      --  <==  this !!
    ... etc. ...
    
    State         MaybeT        t -> (Maybe a, t)      --  <== and this !!
    State         StateT        s -> t -> ((a, s), t)
    ... etc. ...
    

    (This step is a bit painful, since there's a quadratic number of combinations ... but it was a good exercise for me, and I only had to do it once.) The key for me here is that I wrote the combined types unwrapped -- without all those annoying MaybeT, StateT etc. wrappers. It's a lot easier for me to look at and think about the types without the boilerplate.

    To answer your original question, this chart shows that:

    • MaybeT + State :: t -> (Maybe a, t) a stateful computation where there might not be a value, but there will always be a (possibly modified) state output

    • StateT + Maybe :: s -> Maybe (a, s) a computation where both the state and the value may be absent

提交回复
热议问题