
Hi there, I would like to write a GHC plugin — initially as a learning exercise, and maybe real-world use if it works — that automatically applies `liftIO` to `IO` actions, to get the benefit that libraries like `lifted-base` or `relude` provide, but applied to all libraries, automatically. As a simple example, this program will not type-check by default, but it will if I can write my plugin: ``` program :: MonadIO m => m () program = putStrLn "Hello world!" ``` (That's `putStrLn :: String -> IO ()` from the regular `Prelude`) The idea is roughly, "if you see an `IO a` action where a `MonadIO m => m a` action is expected, add `liftIO` to make the `IO a` action type-check. But how to implement it? A type-checker plugin runs when type-checking fails, which is when I want to take action. But it doesn't seem to allow me to change the AST so I can add the `liftIO` function. So then I tried... A `typeCheckResultAction` plugin (for lack of a better name) does allow me to change the AST, and I can use the types to guide how I do it. But it doesn't seem to run if type-checking fails, which is exactly when I want to be adding the `liftIO`s. Am I missing something about GHC's plugin system that would allow me to do what I want? Whether that be AST manipulation in a type-checking plugin, or running the `typeCheckResultAction` despite type-checking failing. Or is AST manipulation with type information impossible if type-checking fails? This is my first foray into anything GHC-related, so I apologize if this doesn't make sense, or isn't the right place to ask. Thanks, - Evan