{-# language ImpredicativeTypes #-} import Control.Monad.Reader.Class (MonadReader) import Control.Monad.IO.Class (MonadIO) f :: f (forall m a. MonadReader () m => m a -> m a) f = undefined g :: f (forall m a. MonadIO m => m a -> m a) g = undefined h1, h2, h3 :: Applicative f => f (forall m a. (MonadReader () m, MonadIO m) => m a -> m a) h1 = (\f g -> f . g) <$> f <*> g h2 = specialisedCompose <$> f <*> g where specialisedCompose :: (forall m a. MonadReader () m => m a -> m a) -> (forall m a. MonadIO m => m a -> m a) -> forall m a. (MonadReader () m, MonadIO m) => m a -> m a specialisedCompose f g = f . g h3 = generalisedCompose <$> f <*> g where generalisedCompose f g = f . g main = putStrLn "hello"