
Anders Kaseorg wrote:
On Wed, 14 Apr 2010, Anders Kaseorg wrote:
class Monad m => MonadMorphIO m where morphIO :: (forall b. (m a -> IO b) -> IO b) -> m a
I’d like to experimentally publish this on Hackage. Here are some questions, at least a few of which should ideally have answers before I do so:
• Any ideas for what it should be named? I have to admit that I picked “morph” as a relatively generic word that doesn’t really mean anything. I wanted to call it “wrap” but discovered that MonadWrap had been taken by the monad-wrap package, which actually has a very similar goal but is slightly less general (it doesn’t support ContT).
How about renaming morph to liftControl ? This makes it explicit that the point is to lift control operators.
• What useful functions should be wrapped with it? Some candidates are catch, block, unblock (and friends from Control.Exception), forkIO, runInBoundThread, runInUnboundThread, unsafeInterleaveIO, withProgName, withArgs, alloca (and friends from Foreign.Marshal), withMVar, modifyMVar_, modifyMVar. Then of course there are all the functions that could be wrapped with liftIO…
I think it's best to wrap just a few functions like catch and forkIO and then thoroughly document how to lift your own.
• How should this relate to MonadIO? Should MonadMorphIO eventually replace MonadIO entirely? For that matter, should MonadTransMorph replace MonadTrans?
It cannot be a replacement because MonadTransMorph is strictly more powerful than MonadTrans (same for IO): not every instance of MonadTrans can also be an instance of MonadTransMorph. This is why I suspect there could be something wrong with the ContT instance. Hard to tell without having a clear specification of what should be right.
• Maybe I’m thinking way too far ahead, and I should just release it now and watch from a safe distance to see what happens?
A little thought can never hurt. ;) Regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com