
killThread
can only be called from IO
, but perhaps you mean that it causes an asynchronous interrupt, so it can be received while executing pure code? That is technically true, but I think generally not that interesting—from the point of view of the program, there is no observable difference between an asynchronous interrupt occurring in pure code versus every IO
primitive checking for pending interrupts and raising them.

It is true that throw
is a little more subtle, but I’m not really worried about it, so I’m okay with only dealing with throwIO
.

Well if so much gets baked into a Monad, doesn’t it just become your application context. While Monads can be great for contexts that they can fully encapsulate, I think that certain Monads like IO don’t make sense because they encompass so much and often leak.

I don’t think I quite understand what you’re saying, or whether you’re agreeing or disagreeing! :)