1 {-# OPTIONS -fno-implicit-prelude #-}
2 -----------------------------------------------------------------------------
4 -- Module : Data.Typeable
5 -- Copyright : (c) The University of Glasgow 2001
6 -- License : BSD-style (see the file libraries/base/LICENSE)
8 -- Maintainer : libraries@haskell.org
9 -- Stability : experimental
10 -- Portability : portable
12 -- The Typeable class reifies types to some extent by associating type
13 -- representations to types. These type representations can be compared,
14 -- and one can in turn define a type-safe cast operation. To this end,
15 -- an unsafe cast is guarded by a test for type (representation)
16 -- equivalence. The module Data.Dynamic uses Typeable for an
17 -- implementation of dynamics. The module Data.Generics uses Typeable
18 -- and type-safe cast (but not dynamics) to support the "Scrap your
19 -- boilerplate" style of generic programming.
21 -----------------------------------------------------------------------------
26 -- * The Typeable class
27 Typeable( typeOf ), -- :: a -> TypeRep
29 -- * Type-safe cast and other clients
30 cast, -- :: (Typeable a, Typeable b) => a -> Maybe b
31 sameType, -- two type values are the same
33 -- * Type representations
34 TypeRep, -- abstract, instance of: Eq, Show, Typeable
35 TyCon, -- abstract, instance of: Eq, Show, Typeable
37 -- * Construction of type representations
38 mkTyCon, -- :: String -> TyCon
39 mkAppTy, -- :: TyCon -> [TypeRep] -> TypeRep
40 mkFunTy, -- :: TypeRep -> TypeRep -> TypeRep
41 applyTy, -- :: TypeRep -> TypeRep -> Maybe TypeRep
44 TypeVal, -- view type "a" as "a -> ()"
45 typeVal, -- :: TypeVal a
46 typeValOf, -- :: a -> TypeVal a
47 undefinedType, -- :: TypeVal a -> a
48 withType, -- :: a -> TypeVal a -> a
49 argType, -- :: (a -> b) -> TypeVal a
50 resType, -- :: (a -> b) -> TypeVal b
51 TypeFun -- functions on types
56 import qualified Data.HashTable as HT
61 import Data.List( foldl )
63 #ifdef __GLASGOW_HASKELL__
69 import GHC.Real( rem, Ratio )
71 import GHC.Ptr -- So we can give Typeable instance for Ptr
72 import GHC.Stable -- So we can give Typeable instance for StablePtr
82 #ifdef __GLASGOW_HASKELL__
83 unsafeCoerce :: a -> b
84 unsafeCoerce = unsafeCoerce#
88 import NonStdUnsafeCoerce (unsafeCoerce)
89 import NHC.IOExtras (IORef,newIORef,readIORef,writeIORef,unsafePerformIO)
96 -------------------------------------------------------------
98 -- Type representations
100 -------------------------------------------------------------
103 -- | A concrete representation of a (monomorphic) type. 'TypeRep'
104 -- supports reasonably efficient equality.
105 data TypeRep = TypeRep !Key TyCon [TypeRep]
107 -- Compare keys for equality
108 instance Eq TypeRep where
109 (TypeRep k1 _ _) == (TypeRep k2 _ _) = k1 == k2
111 -- | An abstract representation of a type constructor. 'TyCon' objects can
112 -- be built using 'mkTyCon'.
113 data TyCon = TyCon !Key String
115 instance Eq TyCon where
116 (TyCon t1 _) == (TyCon t2 _) = t1 == t2
121 -- let fTy = mkTyCon "Foo" in show (mkAppTy (mkTyCon ",,")
124 -- returns "(Foo,Foo,Foo)"
126 -- The TypeRep Show instance promises to print tuple types
127 -- correctly. Tuple type constructors are specified by a
128 -- sequence of commas, e.g., (mkTyCon ",,,,") returns
129 -- the 5-tuple tycon.
131 ----------------- Construction --------------------
133 -- | Applies a type constructor to a sequence of types
134 mkAppTy :: TyCon -> [TypeRep] -> TypeRep
135 mkAppTy tc@(TyCon tc_k _) args
136 = TypeRep (appKeys tc_k arg_ks) tc args
138 arg_ks = [k | TypeRep k _ _ <- args]
143 -- | A special case of 'mkAppTy', which applies the function
144 -- type constructor to a pair of types.
145 mkFunTy :: TypeRep -> TypeRep -> TypeRep
146 mkFunTy f a = mkAppTy funTc [f,a]
148 -- | Applies a type to a function type. Returns: @'Just' u@ if the
149 -- first argument represents a function of type @t -> u@ and the
150 -- second argument represents a function of type @t@. Otherwise,
151 -- returns 'Nothing'.
152 applyTy :: TypeRep -> TypeRep -> Maybe TypeRep
153 applyTy (TypeRep _ tc [t1,t2]) t3
154 | tc == funTc && t1 == t3 = Just t2
155 applyTy _ _ = Nothing
157 -- If we enforce the restriction that there is only one
158 -- @TyCon@ for a type & it is shared among all its uses,
159 -- we can map them onto Ints very simply. The benefit is,
160 -- of course, that @TyCon@s can then be compared efficiently.
162 -- Provided the implementor of other @Typeable@ instances
163 -- takes care of making all the @TyCon@s CAFs (toplevel constants),
166 -- If this constraint does turn out to be a sore thumb, changing
167 -- the Eq instance for TyCons is trivial.
169 -- | Builds a 'TyCon' object representing a type constructor. An
170 -- implementation of "Data.Typeable" should ensure that the following holds:
172 -- > mkTyCon "a" == mkTyCon "a"
175 mkTyCon :: String -- ^ the name of the type constructor (should be unique
176 -- in the program, so it might be wise to use the
177 -- fully qualified name).
178 -> TyCon -- ^ A unique 'TyCon' object
179 mkTyCon str = TyCon (mkTyConKey str) str
183 ----------------- Showing TypeReps --------------------
185 instance Show TypeRep where
186 showsPrec p (TypeRep _ tycon tys) =
188 [] -> showsPrec p tycon
189 [x] | tycon == listTc -> showChar '[' . shows x . showChar ']'
190 [a,r] | tycon == funTc -> showParen (p > 8) $
191 showsPrec 9 a . showString " -> " . showsPrec 8 r
192 xs | isTupleTyCon tycon -> showTuple tycon xs
199 instance Show TyCon where
200 showsPrec _ (TyCon _ s) = showString s
202 isTupleTyCon :: TyCon -> Bool
203 isTupleTyCon (TyCon _ (',':_)) = True
204 isTupleTyCon _ = False
206 -- Some (Show.TypeRep) helpers:
208 showArgs :: Show a => [a] -> ShowS
210 showArgs [a] = showsPrec 10 a
211 showArgs (a:as) = showsPrec 10 a . showString " " . showArgs as
213 showTuple :: TyCon -> [TypeRep] -> ShowS
214 showTuple (TyCon _ str) args = showChar '(' . go str args
216 go [] [a] = showsPrec 10 a . showChar ')'
217 go _ [] = showChar ')' -- a failure condition, really.
218 go (',':xs) (a:as) = showsPrec 10 a . showChar ',' . go xs as
219 go _ _ = showChar ')'
222 -------------------------------------------------------------
224 -- The Typeable class
226 -------------------------------------------------------------
228 -- | The class 'Typeable' allows a concrete representation of a type to
230 class Typeable a where
231 typeOf :: a -> TypeRep
232 -- ^ Takes a value of type @a@ and returns a concrete representation
233 -- of that type. The /value/ of the argument should be ignored by
234 -- any instance of 'Typeable', so that it is safe to pass 'undefined' as
238 -------------------------------------------------------------
240 -- Type-safe cast and other clients
242 -------------------------------------------------------------
244 -- | The type-safe cast operation
245 cast :: (Typeable a, Typeable b) => a -> Maybe b
248 r = if typeOf x == typeOf (fromJust r) then
249 Just (unsafeCoerce x)
254 -- | Test for type equivalence
255 sameType :: (Typeable a, Typeable b) => TypeVal a -> TypeVal b -> Bool
256 sameType tva tvb = typeOf (undefinedType tva) ==
257 typeOf (undefinedType tvb)
260 -------------------------------------------------------------
262 -- Instances of the Typeable class for Prelude types
264 -------------------------------------------------------------
267 listTc = mkTyCon "[]"
269 instance Typeable a => Typeable [a] where
270 typeOf ls = mkAppTy listTc [typeOf ((undefined :: [a] -> a) ls)]
272 -- typeOf (undefined :: a)
273 -- using scoped type variables, but we use the
274 -- more verbose form here, for compatibility with Hugs
277 unitTc = mkTyCon "()"
279 instance Typeable () where
280 typeOf _ = mkAppTy unitTc []
285 instance (Typeable a, Typeable b) => Typeable (a,b) where
286 typeOf tu = mkAppTy tup2Tc [typeOf ((undefined :: (a,b) -> a) tu),
287 typeOf ((undefined :: (a,b) -> b) tu)]
290 tup3Tc = mkTyCon ",,"
292 instance ( Typeable a , Typeable b , Typeable c) => Typeable (a,b,c) where
293 typeOf tu = mkAppTy tup3Tc [typeOf ((undefined :: (a,b,c) -> a) tu),
294 typeOf ((undefined :: (a,b,c) -> b) tu),
295 typeOf ((undefined :: (a,b,c) -> c) tu)]
298 tup4Tc = mkTyCon ",,,"
300 instance ( Typeable a
303 , Typeable d) => Typeable (a,b,c,d) where
304 typeOf tu = mkAppTy tup4Tc [typeOf ((undefined :: (a,b,c,d) -> a) tu),
305 typeOf ((undefined :: (a,b,c,d) -> b) tu),
306 typeOf ((undefined :: (a,b,c,d) -> c) tu),
307 typeOf ((undefined :: (a,b,c,d) -> d) tu)]
309 tup5Tc = mkTyCon ",,,,"
311 instance ( Typeable a
315 , Typeable e) => Typeable (a,b,c,d,e) where
316 typeOf tu = mkAppTy tup5Tc [typeOf ((undefined :: (a,b,c,d,e) -> a) tu),
317 typeOf ((undefined :: (a,b,c,d,e) -> b) tu),
318 typeOf ((undefined :: (a,b,c,d,e) -> c) tu),
319 typeOf ((undefined :: (a,b,c,d,e) -> d) tu),
320 typeOf ((undefined :: (a,b,c,d,e) -> e) tu)]
322 instance (Typeable a, Typeable b) => Typeable (a -> b) where
323 typeOf f = mkFunTy (typeOf ((undefined :: (a -> b) -> a) f))
324 (typeOf ((undefined :: (a -> b) -> b) f))
327 -------------------------------------------------------------
331 -------------------------------------------------------------
335 This group provides a style of encoding types as values and using
336 them. This style is seen as an alternative to the pragmatic style used
337 in Data.Typeable.typeOf and elsewhere, i.e., simply use an "undefined"
338 to denote a type argument. This pragmatic style suffers from lack
339 of robustness: one feels tempted to pattern match on undefineds.
340 Maybe Data.Typeable.typeOf etc. should be rewritten accordingly.
345 -- | Type as values to stipulate use of undefineds
346 type TypeVal a = a -> ()
349 -- | The value that denotes a type
354 -- | Map a value to its type
355 typeValOf :: a -> TypeVal a
356 typeValOf _ = typeVal
359 -- | Stipulate this idiom!
360 undefinedType :: TypeVal a -> a
361 undefinedType _ = undefined
364 -- | Constrain a type
365 withType :: a -> TypeVal a -> a
369 -- | The argument type of a function
370 argType :: (a -> b) -> TypeVal a
374 -- | The result type of a function
375 resType :: (a -> b) -> TypeVal b
380 -- i.e., functions mapping types to values
382 type TypeFun a r = TypeVal a -> r
386 -------------------------------------------------------
388 -- Generate Typeable instances for standard datatypes
390 -------------------------------------------------------
393 INSTANCE_TYPEABLE0(Bool,boolTc,"Bool")
394 INSTANCE_TYPEABLE0(Char,charTc,"Char")
395 INSTANCE_TYPEABLE0(Float,floatTc,"Float")
396 INSTANCE_TYPEABLE0(Double,doubleTc,"Double")
397 INSTANCE_TYPEABLE0(Int,intTc,"Int")
398 INSTANCE_TYPEABLE0(Integer,integerTc,"Integer")
399 INSTANCE_TYPEABLE1(Ratio,ratioTc,"Ratio")
400 INSTANCE_TYPEABLE2(Either,eitherTc,"Either")
401 INSTANCE_TYPEABLE1(IO,ioTc,"IO")
402 INSTANCE_TYPEABLE1(Maybe,maybeTc,"Maybe")
403 INSTANCE_TYPEABLE0(Ordering,orderingTc,"Ordering")
404 INSTANCE_TYPEABLE0(Handle,handleTc,"Handle")
405 INSTANCE_TYPEABLE1(Ptr,ptrTc,"Ptr")
406 INSTANCE_TYPEABLE1(StablePtr,stablePtrTc,"StablePtr")
408 INSTANCE_TYPEABLE0(Int8,int8Tc,"Int8")
409 INSTANCE_TYPEABLE0(Int16,int16Tc,"Int16")
410 INSTANCE_TYPEABLE0(Int32,int32Tc,"Int32")
411 INSTANCE_TYPEABLE0(Int64,int64Tc,"Int64")
413 INSTANCE_TYPEABLE0(Word8,word8Tc,"Word8" )
414 INSTANCE_TYPEABLE0(Word16,word16Tc,"Word16")
415 INSTANCE_TYPEABLE0(Word32,word32Tc,"Word32")
416 INSTANCE_TYPEABLE0(Word64,word64Tc,"Word64")
418 INSTANCE_TYPEABLE0(TyCon,tyconTc,"TyCon")
419 INSTANCE_TYPEABLE0(TypeRep,typeRepTc,"TypeRep")
421 INSTANCE_TYPEABLE1(IORef,ioRefTc,"IORef")
425 ---------------------------------------------
429 ---------------------------------------------
432 newtype Key = Key Int deriving( Eq )
435 data KeyPr = KeyPr !Key !Key deriving( Eq )
437 hashKP :: KeyPr -> Int32
438 hashKP (KeyPr (Key k1) (Key k2)) = (HT.hashInt k1 + HT.hashInt k2) `rem` HT.prime
440 data Cache = Cache { next_key :: !(IORef Key),
441 tc_tbl :: !(HT.HashTable String Key),
442 ap_tbl :: !(HT.HashTable KeyPr Key) }
444 {-# NOINLINE cache #-}
446 cache = unsafePerformIO $ do
447 empty_tc_tbl <- HT.new (==) HT.hashString
448 empty_ap_tbl <- HT.new (==) hashKP
449 key_loc <- newIORef (Key 1)
450 return (Cache { next_key = key_loc,
451 tc_tbl = empty_tc_tbl,
452 ap_tbl = empty_ap_tbl })
454 newKey :: IORef Key -> IO Key
455 newKey kloc = do { k@(Key i) <- readIORef kloc ;
456 writeIORef kloc (Key (i+1)) ;
459 mkTyConKey :: String -> Key
461 = unsafePerformIO $ do
462 let Cache {next_key = kloc, tc_tbl = tbl} = cache
463 mb_k <- HT.lookup tbl str
466 Nothing -> do { k <- newKey kloc ;
467 HT.insert tbl str k ;
470 appKey :: Key -> Key -> Key
472 = unsafePerformIO $ do
473 let Cache {next_key = kloc, ap_tbl = tbl} = cache
474 mb_k <- HT.lookup tbl kpr
477 Nothing -> do { k <- newKey kloc ;
478 HT.insert tbl kpr k ;
483 appKeys :: Key -> [Key] -> Key
484 appKeys k ks = foldl appKey k ks