I'm thinking about ways to use Haskell's type system to enforce modularity in a program. For example, if I have a web application, I'm curious if there's a way to separate all database code from CGI code from filesystem code from pure code.
For example, I'm envisioning a DB monad, so I could write functions like:
countOfUsers :: DB Int
countOfUsers = select "count(*) from users"
I would like it to be impossible to use side effects other than those supported by the DB monad. I am picturing a higher-level monad that would be limited to direct URL handlers and would be able to compose calls to the DB monad and the IO monad.
Is this possible? Is this wise?