{-# LANGUAGE Trustworthy #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE TypeApplications #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Typeable.Internal -- Copyright : (c) The University of Glasgow, CWI 2001--2011 -- License : BSD-style (see the file libraries/base/LICENSE) -- -- The representations of the types TyCon and TypeRep, and the -- function mkTyCon which is used by derived instances of Typeable to -- construct a TyCon. -- ----------------------------------------------------------------------------- module Data.Typeable.Internal ( Proxy (..), Fingerprint(..), -- * Typeable class typeOf, typeOf1, typeOf2, typeOf3, typeOf4, typeOf5, typeOf6, typeOf7, Typeable1, Typeable2, Typeable3, Typeable4, Typeable5, Typeable6, Typeable7, -- * Module Module, -- Abstract moduleName, modulePackage, -- * TyCon TyCon, -- Abstract tyConPackage, tyConModule, tyConName, tyConString, tyConFingerprint, mkTyCon3, mkTyCon3#, rnfTyCon, -- * TypeRep TypeRep(..), KindRep, typeRep, mkTyConApp, mkPolyTyConApp, mkAppTy, typeRepTyCon, Typeable(..), mkFunTy, splitTyConApp, splitPolyTyConApp, funResultTy, typeRepArgs, typeRepFingerprint, rnfTypeRep, showsTypeRep, typeRepKinds, typeSymbolTypeRep, typeNatTypeRep ) where import GHC.Base import GHC.Types (TYPE) import GHC.Word import GHC.Show import Data.Proxy import GHC.TypeLits( KnownNat, KnownSymbol, natVal', symbolVal' ) import GHC.Fingerprint.Type import {-# SOURCE #-} GHC.Fingerprint -- loop: GHC.Fingerprint -> Foreign.Ptr -> Data.Typeable -- Better to break the loop here, because we want non-SOURCE imports -- of Data.Typeable as much as possible so we can optimise the derived -- instances. #include "MachDeps.h" {- ********************************************************************* * * The TyCon type * * ********************************************************************* -} modulePackage :: Module -> String modulePackage (Module p _) = trNameString p moduleName :: Module -> String moduleName (Module _ m) = trNameString m tyConPackage :: TyCon -> String tyConPackage (TyCon _ _ m _) = modulePackage m tyConModule :: TyCon -> String tyConModule (TyCon _ _ m _) = moduleName m tyConName :: TyCon -> String tyConName (TyCon _ _ _ n) = trNameString n trNameString :: TrName -> String trNameString (TrNameS s) = unpackCString# s trNameString (TrNameD s) = s -- | Observe string encoding of a type representation {-# DEPRECATED tyConString "renamed to 'tyConName'; 'tyConModule' and 'tyConPackage' are also available." #-} -- deprecated in 7.4 tyConString :: TyCon -> String tyConString = tyConName tyConFingerprint :: TyCon -> Fingerprint tyConFingerprint (TyCon hi lo _ _) = Fingerprint (W64# hi) (W64# lo) mkTyCon3# :: Addr# -- ^ package name -> Addr# -- ^ module name -> Addr# -- ^ the name of the type constructor -> TyCon -- ^ A unique 'TyCon' object mkTyCon3# pkg modl name | Fingerprint (W64# hi) (W64# lo) <- fingerprint = TyCon hi lo (Module (TrNameS pkg) (TrNameS modl)) (TrNameS name) where fingerprint :: Fingerprint fingerprint = fingerprintString (unpackCString# pkg ++ (' ': unpackCString# modl) ++ (' ' : unpackCString# name)) mkTyCon3 :: String -- ^ package name -> String -- ^ module name -> String -- ^ the name of the type constructor -> TyCon -- ^ A unique 'TyCon' object -- Used when the strings are dynamically allocated, -- eg from binary deserialisation mkTyCon3 pkg modl name | Fingerprint (W64# hi) (W64# lo) <- fingerprint = TyCon hi lo (Module (TrNameD pkg) (TrNameD modl)) (TrNameD name) where fingerprint :: Fingerprint fingerprint = fingerprintString (pkg ++ (' ':modl) ++ (' ':name)) isTupleTyCon :: TyCon -> Bool isTupleTyCon tc | ('(':',':_) <- tyConName tc = True | otherwise = False -- | Helper to fully evaluate 'TyCon' for use as @NFData(rnf)@ implementation -- -- @since 4.8.0.0 rnfModule :: Module -> () rnfModule (Module p m) = rnfTrName p `seq` rnfTrName m rnfTrName :: TrName -> () rnfTrName (TrNameS _) = () rnfTrName (TrNameD n) = rnfString n rnfTyCon :: TyCon -> () rnfTyCon (TyCon _ _ m n) = rnfModule m `seq` rnfTrName n rnfString :: [Char] -> () rnfString [] = () rnfString (c:cs) = c `seq` rnfString cs {- ********************************************************************* * * The TypeRep type * * ********************************************************************* -} -- | A concrete representation of a (monomorphic) type. -- 'TypeRep' supports reasonably efficient equality. data TypeRep = TypeRep {-# UNPACK #-} !Fingerprint TyCon [KindRep] [TypeRep] -- NB: For now I've made this lazy so that it's easy to -- optimise code that constructs and deconstructs TypeReps -- perf/should_run/T9203 is a good example -- Also note that mkAppTy does discards the fingerprint, -- so it's a waste to compute it type KindRep = TypeRep -- Compare keys for equality instance Eq TypeRep where TypeRep x _ _ _ == TypeRep y _ _ _ = x == y instance Ord TypeRep where TypeRep x _ _ _ <= TypeRep y _ _ _ = x <= y -- | Observe the 'Fingerprint' of a type representation -- -- @since 4.8.0.0 typeRepFingerprint :: TypeRep -> Fingerprint typeRepFingerprint (TypeRep fpr _ _ _) = fpr -- | Applies a kind-polymorphic type constructor to a sequence of kinds and -- types mkPolyTyConApp :: TyCon -> [KindRep] -> [TypeRep] -> TypeRep {-# INLINE mkPolyTyConApp #-} mkPolyTyConApp tc kinds types = TypeRep (fingerprintFingerprints sub_fps) tc kinds types where !kt_fps = typeRepFingerprints kinds types sub_fps = tyConFingerprint tc : kt_fps typeRepFingerprints :: [KindRep] -> [TypeRep] -> [Fingerprint] -- Builds no thunks typeRepFingerprints kinds types = go1 [] kinds where go1 acc [] = go2 acc types go1 acc (k:ks) = let !fp = typeRepFingerprint k in go1 (fp:acc) ks go2 acc [] = acc go2 acc (t:ts) = let !fp = typeRepFingerprint t in go2 (fp:acc) ts -- | Applies a kind-monomorphic type constructor to a sequence of types mkTyConApp :: TyCon -> [TypeRep] -> TypeRep mkTyConApp tc = mkPolyTyConApp tc [] -- | A special case of 'mkTyConApp', which applies the function -- type constructor to a pair of types. mkFunTy :: TypeRep -> TypeRep -> TypeRep mkFunTy f a = mkTyConApp tcFun [f,a] -- | Splits a type constructor application. -- Note that if the type constructor is polymorphic, this will -- not return the kinds that were used. -- See 'splitPolyTyConApp' if you need all parts. splitTyConApp :: TypeRep -> (TyCon,[TypeRep]) splitTyConApp (TypeRep _ tc _ trs) = (tc,trs) -- | Split a type constructor application splitPolyTyConApp :: TypeRep -> (TyCon,[KindRep],[TypeRep]) splitPolyTyConApp (TypeRep _ tc ks trs) = (tc,ks,trs) -- | Applies a type to a function type. Returns: @'Just' u@ if the -- first argument represents a function of type @t -> u@ and the -- second argument represents a function of type @t@. Otherwise, -- returns 'Nothing'. funResultTy :: TypeRep -> TypeRep -> Maybe TypeRep funResultTy trFun trArg = case splitTyConApp trFun of (tc, [t1,t2]) | tc == tcFun && t1 == trArg -> Just t2 _ -> Nothing tyConOf :: Typeable a => Proxy a -> TyCon tyConOf = typeRepTyCon . typeRep tcFun :: TyCon tcFun = tyConOf (Proxy :: Proxy (Int -> Int)) -- | Adds a TypeRep argument to a TypeRep. mkAppTy :: TypeRep -> TypeRep -> TypeRep {-# INLINE mkAppTy #-} mkAppTy (TypeRep _ tc ks trs) arg_tr = mkPolyTyConApp tc ks (trs ++ [arg_tr]) -- Notice that we call mkTyConApp to construct the fingerprint from tc and -- the arg fingerprints. Simply combining the current fingerprint with -- the new one won't give the same answer, but of course we want to -- ensure that a TypeRep of the same shape has the same fingerprint! -- See Trac #5962 ----------------- Observation --------------------- -- | Observe the type constructor of a type representation typeRepTyCon :: TypeRep -> TyCon typeRepTyCon (TypeRep _ tc _ _) = tc -- | Observe the argument types of a type representation typeRepArgs :: TypeRep -> [TypeRep] typeRepArgs (TypeRep _ _ _ tys) = tys -- | Observe the argument kinds of a type representation typeRepKinds :: TypeRep -> [KindRep] typeRepKinds (TypeRep _ _ ks _) = ks {- ********************************************************************* * * The Typeable class * * ********************************************************************* -} ------------------------------------------------------------- -- -- The Typeable class and friends -- ------------------------------------------------------------- -- | The class 'Typeable' allows a concrete representation of a type to -- be calculated. class Typeable a where typeRep# :: Proxy# a -> TypeRep -- | Takes a value of type @a@ and returns a concrete representation -- of that type. -- -- @since 4.7.0.0 typeRep :: forall proxy a. Typeable a => proxy a -> TypeRep typeRep _ = typeRep# (proxy# :: Proxy# a) {-# INLINE typeRep #-} -- Keeping backwards-compatibility typeOf :: forall a. Typeable a => a -> TypeRep typeOf _ = typeRep (Proxy :: Proxy a) typeOf1 :: forall t (a :: *). Typeable t => t a -> TypeRep typeOf1 _ = typeRep (Proxy :: Proxy t) typeOf2 :: forall t (a :: *) (b :: *). Typeable t => t a b -> TypeRep typeOf2 _ = typeRep (Proxy :: Proxy t) typeOf3 :: forall t (a :: *) (b :: *) (c :: *). Typeable t => t a b c -> TypeRep typeOf3 _ = typeRep (Proxy :: Proxy t) typeOf4 :: forall t (a :: *) (b :: *) (c :: *) (d :: *). Typeable t => t a b c d -> TypeRep typeOf4 _ = typeRep (Proxy :: Proxy t) typeOf5 :: forall t (a :: *) (b :: *) (c :: *) (d :: *) (e :: *). Typeable t => t a b c d e -> TypeRep typeOf5 _ = typeRep (Proxy :: Proxy t) typeOf6 :: forall t (a :: *) (b :: *) (c :: *) (d :: *) (e :: *) (f :: *). Typeable t => t a b c d e f -> TypeRep typeOf6 _ = typeRep (Proxy :: Proxy t) typeOf7 :: forall t (a :: *) (b :: *) (c :: *) (d :: *) (e :: *) (f :: *) (g :: *). Typeable t => t a b c d e f g -> TypeRep typeOf7 _ = typeRep (Proxy :: Proxy t) type Typeable1 (a :: * -> *) = Typeable a type Typeable2 (a :: * -> * -> *) = Typeable a type Typeable3 (a :: * -> * -> * -> *) = Typeable a type Typeable4 (a :: * -> * -> * -> * -> *) = Typeable a type Typeable5 (a :: * -> * -> * -> * -> * -> *) = Typeable a type Typeable6 (a :: * -> * -> * -> * -> * -> * -> *) = Typeable a type Typeable7 (a :: * -> * -> * -> * -> * -> * -> * -> *) = Typeable a {-# DEPRECATED Typeable1 "renamed to 'Typeable'" #-} -- deprecated in 7.8 {-# DEPRECATED Typeable2 "renamed to 'Typeable'" #-} -- deprecated in 7.8 {-# DEPRECATED Typeable3 "renamed to 'Typeable'" #-} -- deprecated in 7.8 {-# DEPRECATED Typeable4 "renamed to 'Typeable'" #-} -- deprecated in 7.8 {-# DEPRECATED Typeable5 "renamed to 'Typeable'" #-} -- deprecated in 7.8 {-# DEPRECATED Typeable6 "renamed to 'Typeable'" #-} -- deprecated in 7.8 {-# DEPRECATED Typeable7 "renamed to 'Typeable'" #-} -- deprecated in 7.8 ----------------- Showing TypeReps -------------------- instance Show TypeRep where showsPrec p (TypeRep _ tycon kinds tys) = case tys of [] -> showsPrec p tycon [x] | tycon == tcList -> showChar '[' . shows x . showChar ']' where tcList = tyConOf @[] Proxy [TypeRep _ ptrRepCon _ []] | tycon == tcTYPE && ptrRepCon == tc'PtrRepLifted -> showChar '*' | tycon == tcTYPE && ptrRepCon == tc'PtrRepUnlifted -> showChar '#' where tcTYPE = tyConOf @TYPE Proxy tc'PtrRepLifted = tyConOf @'PtrRepLifted Proxy tc'PtrRepUnlifted = tyConOf @'PtrRepUnlifted Proxy [a,r] | tycon == tcFun -> showParen (p > 8) $ showsPrec 9 a . showString " -> " . showsPrec 8 r xs | isTupleTyCon tycon -> showTuple xs | otherwise -> showParen (p > 9) $ showsPrec p tycon . showChar ' ' . showArgs (showChar ' ') (kinds ++ tys) showsTypeRep :: TypeRep -> ShowS showsTypeRep = shows -- | Helper to fully evaluate 'TypeRep' for use as @NFData(rnf)@ implementation -- -- @since 4.8.0.0 rnfTypeRep :: TypeRep -> () rnfTypeRep (TypeRep _ tyc krs tyrs) = rnfTyCon tyc `seq` go krs `seq` go tyrs where go [] = () go (x:xs) = rnfTypeRep x `seq` go xs -- Some (Show.TypeRep) helpers: showArgs :: Show a => ShowS -> [a] -> ShowS showArgs _ [] = id showArgs _ [a] = showsPrec 10 a showArgs sep (a:as) = showsPrec 10 a . sep . showArgs sep as showTuple :: [TypeRep] -> ShowS showTuple args = showChar '(' . showArgs (showChar ',') args . showChar ')' {- ********************************************************* * * * TyCon/TypeRep definitions for type literals * * (Symbol and Nat) * * * ********************************************************* -} mkTypeLitTyCon :: String -> TyCon mkTypeLitTyCon name = mkTyCon3 "base" "GHC.TypeLits" name -- | Used to make `'Typeable' instance for things of kind Nat typeNatTypeRep :: KnownNat a => Proxy# a -> TypeRep typeNatTypeRep p = typeLitTypeRep (show (natVal' p)) -- | Used to make `'Typeable' instance for things of kind Symbol typeSymbolTypeRep :: KnownSymbol a => Proxy# a -> TypeRep typeSymbolTypeRep p = typeLitTypeRep (show (symbolVal' p)) -- | An internal function, to make representations for type literals. typeLitTypeRep :: String -> TypeRep typeLitTypeRep nm = mkTyConApp (mkTypeLitTyCon nm) []