
Hi, I'm a hobbyist Haskell programmer and my use of Haskell is mostly consists of writing interpreters, simple virtual machines, and type checkers. One thing I'm not happy about my Haskell programs is, almost all of my programs have a monad transformer stack consisting MonadError, MonadIO and MonadState. Let's say I'm writing an interpreter, I certainly need MonadIO to interpret object language's IO functions: printing, reading from file etc. I also need MonadState for, well, states(dynamic environment etc.). MonadError is also required because most computations can fail(unbound variable error, type mismatch etc. it can be also used for implementing exceptions in object language) Same applies for my other applications as well. Type checkers require MonadError(unification error etc.), MonadState(to keep substitutions). MonadIO is not required in this case. But it also required for virtual machines(IOVector for memory -- ST vectors also work, but IO is still required for other stuff - printing, display etc.) I know these are mostly related with my application area, but I still wanted to write this because I may be missing something, or simply doing things wrong. Advices from experienced Haskell programmers would be appreciated, Cheers, Ömer