Possible runtime overhead of wrapping the IO monad?
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.
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?
More information about the Glasgow-haskell-users