X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Data%2FTypeable.hs;h=f548dc92c6e0ce843e9305961a0c1efd1a4fac86;hb=3a3de8891862f7756f08c816a934506b729139f7;hp=59bc92402ef7d0f1a74eda35646adda41082ce10;hpb=5658e66c8d97ba0fc401c46389e9d5dba2281525;p=ghc-base.git diff --git a/Data/Typeable.hs b/Data/Typeable.hs index 59bc924..f548dc9 100644 --- a/Data/Typeable.hs +++ b/Data/Typeable.hs @@ -25,15 +25,6 @@ -- and type-safe cast (but not dynamics) to support the \"Scrap your -- boilerplate\" style of generic programming. -- --- Note, only relevant if you use dynamic linking. If you have a program --- that is statically linked with Data.Typeable, and then dynamically link --- a program that also uses Data.Typeable, you'll get two copies of the module. --- That's fine, but behind the scenes, the module uses a mutable variable to --- allocate unique Ids to type constructors. So in the situation described, --- there'll be two separate Id allocators, which aren't comparable to each other. --- This can lead to chaos. (It's a bug that we will fix.) None of --- this matters if you aren't using dynamic linking. --- ----------------------------------------------------------------------------- module Data.Typeable @@ -49,6 +40,7 @@ module Data.Typeable -- * Type representations TypeRep, -- abstract, instance of: Eq, Show, Typeable TyCon, -- abstract, instance of: Eq, Show, Typeable + showsTypeRep, -- * Construction of type representations mkTyCon, -- :: String -> TyCon @@ -62,6 +54,7 @@ module Data.Typeable typeRepTyCon, -- :: TypeRep -> TyCon typeRepArgs, -- :: TypeRep -> [TypeRep] tyConString, -- :: TyCon -> String + typeRepKey, -- :: TypeRep -> IO Int -- * The other Typeable classes -- | /Note:/ The general instances are provided for GHC only. @@ -94,6 +87,7 @@ import Data.Either import Data.Int import Data.Word import Data.List( foldl ) +import Unsafe.Coerce #ifdef __GLASGOW_HASKELL__ import GHC.Base @@ -127,19 +121,13 @@ import Hugs.Prelude ( Key(..), TypeRep(..), TyCon(..), Ratio, ArrayException, AsyncException, Handle, Ptr, FunPtr, ForeignPtr, StablePtr ) import Hugs.IORef ( IORef, newIORef, readIORef, writeIORef ) -import Hugs.IOExts ( unsafePerformIO, unsafeCoerce ) +import Hugs.IOExts ( unsafePerformIO ) -- For the Typeable instance import Hugs.Array ( Array ) import Hugs.ConcBase ( MVar ) #endif -#ifdef __GLASGOW_HASKELL__ -unsafeCoerce :: a -> b -unsafeCoerce = unsafeCoerce# -#endif - #ifdef __NHC__ -import NonStdUnsafeCoerce (unsafeCoerce) import NHC.IOExtras (IORef,newIORef,readIORef,writeIORef,unsafePerformIO) import IO (Handle) import Ratio (Ratio) @@ -172,9 +160,21 @@ data TyCon = TyCon !Key String instance Eq TyCon where (TyCon t1 _) == (TyCon t2 _) = t1 == t2 - #endif +-- | Returns a unique integer associated with a 'TypeRep'. This can +-- be used for making a mapping ('Data.IntMap.IntMap') with TypeReps +-- as the keys, for example. It is guaranteed that @t1 == t2@ if and only if +-- @typeRepKey t1 == typeRepKey t2@. +-- +-- It is in the 'IO' monad because the actual value of the key may +-- vary from run to run of the program. You should only rely on +-- the equality property, not any actual key value. The relative ordering +-- of keys has no meaning either. +-- +typeRepKey :: TypeRep -> IO Int +typeRepKey (TypeRep (Key i) _ _) = return i + -- -- let fTy = mkTyCon "Foo" in show (mkTyConApp (mkTyCon ",,") -- [fTy,fTy,fTy]) @@ -276,6 +276,9 @@ instance Show TypeRep where showChar ' ' . showArgs tys +showsTypeRep :: TypeRep -> ShowS +showsTypeRep = shows + instance Show TyCon where showsPrec _ (TyCon _ s) = showString s @@ -643,16 +646,6 @@ newKey kloc = do { k@(Key i) <- readIORef kloc ; #endif #ifdef __GLASGOW_HASKELL__ --- In GHC we use the RTS's genSym function to get a new unique, --- because in GHCi we might have two copies of the Data.Typeable --- library running (one in the compiler and one in the running --- program), and we need to make sure they don't share any keys. --- --- This is really a hack. A better solution would be to centralise the --- whole mutable state used by this module, i.e. both hashtables. But --- the current solution solves the immediate problem, which is that --- dynamics generated in one world with one type were erroneously --- being recognised by the other world as having a different type. foreign import ccall unsafe "genSymZh" genSym :: IO Int #endif