Exactly -- this is an important point Harper misses here. In SML, you can have functions of type "unit -> unit" and have no idea what the heck it is doing. The language allows effects, and so it could be doing
anything. Even a function "int -> int" or whatever could be doing nasty effects behind the scenes. You just can't tell. (Style dictates that non-benign effects in the last case are to be fiercely avoided, but the former case comes up a lot.)
In Haskell, all the effects are encoded into the type. You might have 200 different monad transformers -- maybe monad, list monad, state monad, etc etc all layered on top of each other -- but the information is there if you want to decode what the type means. Effects can sneak in with unsafePerformIO, but this is also considered terrible style. The huge types you can get from all the monads and monad transformers can certainly be a problem, but there's a tradeoff to be considered here that Harper just dismisses.