As described here the class of monads for which StM m a ~ a holds enjoy better compositionality properties than the ones that do not.
This property does not currently hold for MockT, as StM (MockT f) a ~ (a, [WithResult f]). This is a consequence of building MockT f on top of StateT [WithResult f] m, and it limits the applicability of MockT in monad stacks which require a stateless MonadTransControl instance. This is not an academic concern - it happens to be quite common these days.
To address this,MockT can be defined on top of ReaderT (IORef [WithResult f]) m, which possesses a MonadIO instance as long given MonadIO m. Or more generally using MutVar from the primitive package.
Since this incurs in additional constraints for the base monad, it's not a backwards compatible change. An alternative is to add a Control.Monad.Mock.Stateless module with a one-for-one replacement for MockT.
As described here the class of monads for which
StM m a ~ a
holds enjoy better compositionality properties than the ones that do not.This property does not currently hold for
MockT
, asStM (MockT f) a ~ (a, [WithResult f])
. This is a consequence of buildingMockT f
on top ofStateT [WithResult f] m
, and it limits the applicability ofMockT
in monad stacks which require a statelessMonadTransControl
instance. This is not an academic concern - it happens to be quite common these days.To address this,
MockT
can be defined on top ofReaderT (IORef [WithResult f]) m
, which possesses aMonadIO
instance as long givenMonadIO m
. Or more generally usingMutVar
from the primitive package.Since this incurs in additional constraints for the base monad, it's not a backwards compatible change. An alternative is to add a
Control.Monad.Mock.Stateless
module with a one-for-one replacement forMockT
.