Wrapping IO, part 1

I’ve many times heard that Haskell can be used to prevent certain kind of programmer mistakes. In a presentation on Darcs it was explained how GADTs (especially phantom types) are used in Darcs to make sure that operations on patches follow certain rules. Another way, and at least it sounds easier, is to limit the available functions by running code in some sort of container. This being Haskell, that container is often a monad. I’ve really never seen this presented1 , so I thought I’d try to do it, and indeed it turns out to be very simple.

I started with a data type:

newtype HideIO a = HideIO { runHideIO :: IO a }

which I then made into a Monad in order to make it easy to work with:

instance Monad HideIO where
    return = HideIO . return

    (>>=) m f = HideIO $ runHideIO m >>= runHideIO . f

Then I can create an IO function that are allowed in the HideIO monad:

hioPutStrLn = HideIO . putStrLn

In ghci I can then do the following:

> runHideIO $ hioPutStrLn "Hello, World!"
Hello, World!

But I can’t do much else.

  1. Most probably due do my weak searching-fu than anything else.↩︎


Please check the ‘jail’ package on Hackage for another example of this kind of trickery.

Jean-Denis Koeck

You can derive the monad instance like this:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype HideIO a = HideIO { runHideIO :: IO a }


Jean-Denis, cool, and good to know for the future, though it’s hardly good for understanding :-)

Leave a comment