monad-control
monad-control copied to clipboard
Change definition of StT and StM
Hi,
Have you considered defining StT and StM as types of kind (* -> *) and requiring a Functor constraint? i.e.
class (MonadTrans t, Functor (StT t)) => MonadTransControl t where
type StT t :: * -> *
...
class (MonadBase b m, Functor (StM m)) => MondBaseControl b m | m -> b where
type StM m :: * -> *
...
This would not preclude any existing instances in monad-control, and I don't know of any instances anywhere that could not be made to satisfy these constraints. The advantages include:
- The ability to fmap over StT t and StM m
- The ability to get something akin to MonadTransUnlift with the constraint (StM m ~ Identity) rather than the nasty constraints package tricks that are currently necessary.
- The potential to discover other useful subsets of MonadBaseControl b m, such as (Applicative (StM m)). Functor has a lot of subclasses.
Obviously this would break every existing instance, but I think we could come up with some CPP snippets that would cover most cases in a backwards compatible way.
I don't really expect that you would be interested in such a breaking change, but if you were I would be happy to discuss further and to offer my assistance in implementation.
interesting idea...
The ability to get something akin to MonadTransUnlift with the constraint (StM m ~ Identity)
Doesn't work as nicely as we'd wish as Compose Identity Identity
is not Identity
. They are Coercible
though, but that's GHC-7.8+, and I don't think that should be a problem for anyone anymore.
You may be interested in the Tunnel
type of monadology
, it's basically this idea. These are the instances:
type Tunnel (ReaderT s) = Identity
type Tunnel (WriterT w) = (,) w
type Tunnel (StateT s) = (,) (Endo s)
type Tunnel MaybeT = Maybe
type Tunnel (ExceptT e) = Either e
type Tunnel (ComposeInner inner) = inner
type Tunnel (ComposeOuter outer) = Identity
It's not just Functor (Tunnel t)
, there's actually the much stronger constraint MonadInner (Tunnel t)
. MonadInner
is the class of monads that can compose (as the inner monad) with any other monad to make a monad. I use this to enable commuting of transformers within the stack (commuteT
).
Overall it's a cleaner and more powerful approach than the current MonadTransControl
.