I don't see any reason to be more abstract than we need to, just like I don't think `putStrLn` should have type `MonadIO m => String -> m ()` rather than `String -> IO ()`. We have a means to compose applicatives in a principled way and execute them that doesn't run into the usual pitfalls of monad transformers (which are, as you yourself pointed out, not very composable).