Possible runtime overhead of wrapping the IO monad?

Brian Hulley brianh at metamilk.com
Mon Mar 27 14:14:40 EST 2006

I'm designing an API for a simple graphics window, and am trying to make the 
correct usage of the API functions explicit and visible to the type system 
by using different monads which ultimately just wrap the IO monad. For 
example, in a callback for rendering stuff to the screen, only operations in 
the RenderM monad are allowed, and when specifying vertex info for a 
primitive, only VertexM operations are allowed.

However I'm wondering if I can rely on all this monad stuff being optimized 
out at compile time. A sample monad is below:

   newtype VertexM a = VertexM (IO a)

   instance Monad VertexM where
      VertexM x >>= fry = VertexM $ do
          ax <- x
          let VertexM y = fry ax

      return x = VertexM $ return x

   instance MonadIO VertexM where
      liftIO = VertexM

The monad doesn't do anything interesting apart from allowing the type 
checker to reject programs that don't use the API the way it was intended 
(all these things you have to keep in your head in C programs), but I don't 
want to use it if I'm going to get a performance hit.

Also, in:

   foreign import ccall duma_vertex3f :: Float -> Float -> Float -> IO ()

   vertex3f :: Float -> Float -> Float -> VertexM ()
   vertex3f x y z = liftIO $ duma_vertex3f x y z

is there a penalty involved in calling vertex3f (from another module) or 
will the worker/wrapper optimization ensure that machine code in the other 
module just calls duma_vertex3f directly since the liftIO operation is just 
an irrelevance at the machine code level?

So far I've just been using ghc --make and not bothering about what kind of 
code is generated. Is there a flag I can use to get ghc to output the stg 
code (or something higher level than just x86 machine code itself) so I can 
look at the output to see what optimizations are being done?

Thanks, Brian.

More information about the Glasgow-haskell-users mailing list