Efficiency of using field labels vs pattern matching
Brian Hulley
brianh at metamilk.com
Sun Aug 20 13:39:59 EDT 2006
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
More information about the Glasgow-haskell-users
mailing list