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

前端 未结 5 1447
你的背包
你的背包 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:44

    Let's pretend that rather than using State/StateT to store your procedures' state, you were using an IORef in the IO monad.

    A priori there are two ways you could want mzero (or fail) to behave in a combination of the IO and Maybe monads:

    • either mzero wipes out the entire computation, so that mzero <|> x = x; or
    • mzero causes the current computation to not return a value, but IO-type effects are preserved.

    It sounds like you want the first one, so that the state set by one procedure is "unrolled" for the next procedure in a chain of <|>s.

    Of course, this semantics is impossible to implement. We don't know whether a computation will invoke mzero until we run it, but doing so may have arbitrary IO effects like launchTheMissiles, which we can't roll back.

    Now, let's try to build two different monad transformer stacks out of Maybe and IO:

    • IOT Maybe -- oops, this doesn't exist!
    • MaybeT IO

    The one that exists (MaybeT IO) gives the mzero behavior that is possible, and the nonexistent IOT Maybe corresponds to the other behavior.

    Fortunately you're using State ProcedureState, whose effects can be rolled back, rather than IO; the monad transformer stack you want is the StateT ProcedureState Maybe one.

提交回复
热议问题