
Sigbjorn Finne wrote:
If you let the Simplifier have a crack at your code (i.e., compile with -O or better), the same code should be generated for the two defns of 'foo'. Try compiling with -ddump-simpl to verify.
Thanks. I tried that and you're right. It also works well with an even more complicated example: data R = R{_xRef :: !(Ref.T Int), _y :: Int} foo :: Bool -> R -> IO () foo b r = do if b then Ref.write (_xRef r) ((_y r) * (_y r)) else return () x <- Ref.read (_xRef r) print x Even though there are 4 applications of field label functions and _y is not even a strict field, GHC -O2 manages to get both fields with a single case statement: Main.foo :: GHC.Base.Bool -> Main.R -> GHC.IOBase.IO () [GlobalId] [Arity 3 Worker Main.$wfoo Str: DmdType SU(U(L)L)L] Main.foo = __inline_me (\ (w_s2sp :: GHC.Base.Bool) (w1_s2sq :: Main.R) (w2_s2sy :: GHC.Prim.State# GHC.Prim.RealWorld) -> case (# GHC.Prim.State# GHC.Prim.RealWorld, () #) w1_s2sq of w3_X2sB { Main.R ww_s2ss ww1_s2sw -> -- well done GHC!!!! :-) case (# GHC.Prim.State# GHC.Prim.RealWorld, () #) ww_s2ss of ww2_X2sI { GHC.STRef.STRef ww3_s2su -> Main.$wfoo w_s2sp ww3_s2su ww1_s2sw w2_s2sy } }) This is great because some of my records have about 20 fields so the pattern matching was getting really cumbersome in the source. BTW I made a module to make the IORef functions work with any MonadIO and also give them better names (to use by qualified import) which I enclose below if anyone is interested - I don't know where to put stuff like this: ---------------------------------------------------------------- -- | -- Module: Prime.IORef -- Author: Brian Hulley -- License: Public Domain -- -- Lifts (most of) Data.IORef to any MonadIO -- This module should be used qualified so we can avoid -- writing "IORef" everywhere ---------------------------------------------------------------- module Prime.IORef ( T , new , read , write , modify , weak ) where import Prelude hiding(read) import qualified Data.IORef as D import Control.Monad.Trans import System.Mem.Weak type T = D.IORef new :: MonadIO m => a -> m (T a) new x = liftIO $ D.newIORef x read :: MonadIO m => T a -> m a read x = liftIO $ D.readIORef x write :: MonadIO m => T a -> a -> m () write x v = liftIO $ D.writeIORef x v modify :: MonadIO m => T a -> (a -> a) -> m () modify x f = liftIO $ D.modifyIORef x f weak :: MonadIO m => T a -> m (Weak (T a)) weak r = liftIO $ D.mkWeakIORef r (return ()) Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com