I can't remember the exact monad names, but Redis transactions are in a specific Monad that does not give you access to IO. I don't know whether that's functionality provided by Hedis or whether we wrote that.
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.
Yes of course, but it's a next step to actually use that ability. Very cool that you do :) It takes some tough developer discipline to deprive yourself from the power or the IO monad.
It might take some developer discipline to set things up that way initially, but the great thing about Haskell is that once you have it set up, it does not require any developer discipline. If your system runs in the Foo monad, you can only do operations that have been made available to you. This is the big problem that other languages have...you simply cannot enforce some of these guarantees.
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.