Where are the Applicative transformer classes? I wanted to use transformer classes for the applicative transformer stack in a previous answer, but they don't seem to exist.
The transformers package and many others are full of transformers that preserver Applicative structure, even when the underlying structure isn't a Monad.
A quick glance at transformers has Applicative instances for most of the transformers.
Applicative f => Applicative (Backwards f)
Applicative f => Applicative (Lift f)
Applicative (ContT r m)
Applicative m => Applicative (IdentityT m)
Applicative m => Applicative (ReaderT r m)
(Monoid w, Applicative m) => Applicative (WriterT w m)
(Applicative f, Applicative g) => Applicative (Compose f g)
(Applicative f, Applicative g) => Applicative (Product f g)
Only transformers for state and alternation (ExceptT and MaybeT) require an underlying monad for the Applicative instance.
(Functor m, Monad m) => Applicative (ExceptT e m)
(Functor m, Monad m) => Applicative (MaybeT m)
(Monoid w, Functor m, Monad m) => Applicative (RWST r w s m)
(Functor m, Monad m) => Applicative (StateT s m)
There's a class for Monad transformers. I can see how something could require this Monad constraint, since it can't be introduced elsewhere.
class MonadTrans t where
lift :: (Monad m) => m a -> t m a
Where's the class for Applicative transformers?
class ApTrans t where
liftAp :: (Applicative f) => f a -> t f a
Or just plain old transformers (though I can't imagine any laws for this)?
class Trans t where
liftAny :: f a -> t f a
Due to the difference only in polymorphic constraints, these typeclasses have a strange variance pattern. Except for their laws, which have to consider unexpressible constraints, anything that is an instance of Trans should automatically be an instance of ApTrans and MonadTrans, and anything that's an instance of ApTrans should automatically be an instance of MonadTrans.
If we move on to the mtl library, the classes there are also incompatible with an Applicative transformer stack. All of the mtl classes I'm familiar with have a Monad constraint. For example, here's MonadReader
class Monad m => MonadReader r m | m -> r where
-- | Retrieves the monad environment.
ask :: m r
ask = reader id
-- | Executes a computation in a modified environment.
local :: (r -> r) -- ^ The function to modify the environment.
-> m a -- ^ @Reader@ to run in the modified environment.
-> m a
-- | Retrieves a function of the current environment.
reader :: (r -> a) -- ^ The selector function to apply to the environment.
-> m a
reader f = do
r <- ask
return (f r)
What is the purpose of the Monad constraint? It makes MonadReader and the MonadReader instances for many of the above transformers incompatible with Applicative transformer stacks.
I would naively write something like
class Reader r m | m -> r where
ask :: m r
local :: (r -> r) -> m a -> m a
or even split local into a separate class.
class Reader r m | m -> r where
ask :: m r
class (Reader r m) => Local r m | m -> r where
local :: (r -> r) -> m a -> m a
local might be quite hard to use without a Monad instance. A more useful interface without the Monad constraint would be something like
class (Reader r m) => Local r m | m -> r where
local :: m (r -> r) -> m a -> m a
Are there existing transformer classes somewhere that don't have the Monad constraint, or is there an actual need for yet another transformer class library?