We have a general Monad typeclass called "World" which gives access to MySQL, Redis, HTTP, Memcache, and so on. There are more specific Monad typeclasses if you have a function that, for example, should only ever talk to Memcache and nothing else. I think it's called SupportsMemcache.
My point about the Haskell type system is that the _ability_ to limit the operations in a context is a capability that few languages have.
We have a simple mechanism for controlling access to IO.
There are a series of type classes that provide access to all of the IO based services (mysql, redis, memcache, etc.). All of the request handlers are written to use these type classes not IO. There are two instances of the type classes, one pure for tests using fakes, and one real using IO.
Do you have a policy around the use of I/O monads versus specialized monads for controlling access like that?