61b70cfd2e40d76e5ae0245a1756461da8488ba2
[ghc.git] / libraries / base / Data / Typeable.hs
1 {-# LANGUAGE Trustworthy #-}
2 {-# LANGUAGE GADTs #-}
3 {-# LANGUAGE NoImplicitPrelude #-}
4 {-# LANGUAGE PolyKinds #-}
5 {-# LANGUAGE ScopedTypeVariables #-}
6 {-# LANGUAGE ConstraintKinds #-}
7 {-# LANGUAGE PatternSynonyms #-}
8 {-# LANGUAGE TypeOperators #-}
9
10 -----------------------------------------------------------------------------
11 -- |
12 -- Module : Data.Typeable
13 -- Copyright : (c) The University of Glasgow, CWI 2001--2004
14 -- License : BSD-style (see the file libraries/base/LICENSE)
15 --
16 -- Maintainer : libraries@haskell.org
17 -- Stability : experimental
18 -- Portability : portable
19 --
20 -- The 'Typeable' class reifies types to some extent by associating type
21 -- representations to types. These type representations can be compared,
22 -- and one can in turn define a type-safe cast operation. To this end,
23 -- an unsafe cast is guarded by a test for type (representation)
24 -- equivalence. The module "Data.Dynamic" uses Typeable for an
25 -- implementation of dynamics. The module "Data.Data" uses Typeable
26 -- and type-safe cast (but not dynamics) to support the \"Scrap your
27 -- boilerplate\" style of generic programming.
28 --
29 -- == Compatibility Notes
30 --
31 -- Since GHC 8.2, GHC has supported type-indexed type representations.
32 -- "Data.Typeable" provides type representations which are qualified over this
33 -- index, providing an interface very similar to the "Typeable" notion seen in
34 -- previous releases. For the type-indexed interface, see "Type.Reflection".
35 --
36 -- Since GHC 7.8, 'Typeable' is poly-kinded. The changes required for this might
37 -- break some old programs involving 'Typeable'. More details on this, including
38 -- how to fix your code, can be found on the
39 -- <https://ghc.haskell.org/trac/ghc/wiki/GhcKinds/PolyTypeable PolyTypeable wiki page>
40 --
41 -----------------------------------------------------------------------------
42
43 module Data.Typeable
44 ( -- * The Typeable class
45 Typeable
46 , typeOf
47 , typeRep
48
49 -- * Propositional equality
50 , (:~:)(Refl)
51 , (:~~:)(HRefl)
52
53 -- * Type-safe cast
54 , cast
55 , eqT
56 , gcast -- a generalisation of cast
57
58 -- * Generalized casts for higher-order kinds
59 , gcast1 -- :: ... => c (t a) -> Maybe (c (t' a))
60 , gcast2 -- :: ... => c (t a b) -> Maybe (c (t' a b))
61
62 -- * A canonical proxy type
63 , Proxy (..)
64
65 -- * Type representations
66 , TypeRep
67 , rnfTypeRep
68 , showsTypeRep
69 , mkFunTy
70
71 -- * Observing type representations
72 , funResultTy
73 , splitTyConApp
74 , typeRepArgs
75 , typeRepTyCon
76 , typeRepFingerprint
77
78 -- * Type constructors
79 , I.TyCon -- abstract, instance of: Eq, Show, Typeable
80 -- For now don't export Module to avoid name clashes
81 , I.tyConPackage
82 , I.tyConModule
83 , I.tyConName
84 , I.rnfTyCon
85 , I.tyConFingerprint
86
87 -- * For backwards compatibility
88 , typeOf1, typeOf2, typeOf3, typeOf4, typeOf5, typeOf6, typeOf7
89 ) where
90
91 import qualified Data.Typeable.Internal as I
92 import Data.Typeable.Internal (Typeable)
93 import Data.Type.Equality
94
95 import Data.Maybe
96 import Data.Proxy
97 import GHC.Fingerprint.Type
98 import GHC.Show
99 import GHC.Base
100
101 -- | A quantified type representation.
102 type TypeRep = I.SomeTypeRep
103
104 -- | Observe a type representation for the type of a value.
105 typeOf :: forall a. Typeable a => a -> TypeRep
106 typeOf _ = I.someTypeRep (Proxy :: Proxy a)
107
108 -- | Takes a value of type @a@ and returns a concrete representation
109 -- of that type.
110 --
111 -- @since 4.7.0.0
112 typeRep :: forall proxy a. Typeable a => proxy a -> TypeRep
113 typeRep = I.someTypeRep
114
115 -- | Show a type representation
116 showsTypeRep :: TypeRep -> ShowS
117 showsTypeRep = shows
118
119 -- | The type-safe cast operation
120 cast :: forall a b. (Typeable a, Typeable b) => a -> Maybe b
121 cast x
122 | Just HRefl <- ta `I.eqTypeRep` tb = Just x
123 | otherwise = Nothing
124 where
125 ta = I.typeRep :: I.TypeRep a
126 tb = I.typeRep :: I.TypeRep b
127
128 -- | Extract a witness of equality of two types
129 --
130 -- @since 4.7.0.0
131 eqT :: forall a b. (Typeable a, Typeable b) => Maybe (a :~: b)
132 eqT
133 | Just HRefl <- ta `I.eqTypeRep` tb = Just Refl
134 | otherwise = Nothing
135 where
136 ta = I.typeRep :: I.TypeRep a
137 tb = I.typeRep :: I.TypeRep b
138
139 -- | A flexible variation parameterised in a type constructor
140 gcast :: forall a b c. (Typeable a, Typeable b) => c a -> Maybe (c b)
141 gcast x = fmap (\Refl -> x) (eqT :: Maybe (a :~: b))
142
143 -- | Cast over @k1 -> k2@
144 gcast1 :: forall c t t' a. (Typeable t, Typeable t')
145 => c (t a) -> Maybe (c (t' a))
146 gcast1 x = fmap (\Refl -> x) (eqT :: Maybe (t :~: t'))
147
148 -- | Cast over @k1 -> k2 -> k3@
149 gcast2 :: forall c t t' a b. (Typeable t, Typeable t')
150 => c (t a b) -> Maybe (c (t' a b))
151 gcast2 x = fmap (\Refl -> x) (eqT :: Maybe (t :~: t'))
152
153 -- | Applies a type to a function type. Returns: @Just u@ if the first argument
154 -- represents a function of type @t -> u@ and the second argument represents a
155 -- function of type @t@. Otherwise, returns @Nothing@.
156 funResultTy :: TypeRep -> TypeRep -> Maybe TypeRep
157 funResultTy (I.SomeTypeRep f) (I.SomeTypeRep x)
158 | Just HRefl <- (I.typeRep :: I.TypeRep Type) `I.eqTypeRep` I.typeRepKind f
159 , I.Fun arg res <- f
160 , Just HRefl <- arg `I.eqTypeRep` x
161 = Just (I.SomeTypeRep res)
162 | otherwise = Nothing
163
164 -- | Build a function type.
165 mkFunTy :: TypeRep -> TypeRep -> TypeRep
166 mkFunTy (I.SomeTypeRep arg) (I.SomeTypeRep res)
167 | Just HRefl <- I.typeRepKind arg `I.eqTypeRep` liftedTy
168 , Just HRefl <- I.typeRepKind res `I.eqTypeRep` liftedTy
169 = I.SomeTypeRep (I.Fun arg res)
170 | otherwise
171 = error $ "mkFunTy: Attempted to construct function type from non-lifted "++
172 "type: arg="++show arg++", res="++show res
173 where liftedTy = I.typeRep :: I.TypeRep Type
174
175 -- | Splits a type constructor application. Note that if the type constructor is
176 -- polymorphic, this will not return the kinds that were used.
177 splitTyConApp :: TypeRep -> (TyCon, [TypeRep])
178 splitTyConApp (I.SomeTypeRep x) = I.splitApps x
179
180 -- | Observe the argument types of a type representation
181 typeRepArgs :: TypeRep -> [TypeRep]
182 typeRepArgs ty = case splitTyConApp ty of (_, args) -> args
183
184 -- | Observe the type constructor of a quantified type representation.
185 typeRepTyCon :: TypeRep -> TyCon
186 typeRepTyCon = I.someTypeRepTyCon
187
188 -- | Takes a value of type @a@ and returns a concrete representation
189 -- of that type.
190 --
191 -- @since 4.7.0.0
192 typeRepFingerprint :: TypeRep -> Fingerprint
193 typeRepFingerprint = I.someTypeRepFingerprint
194
195 -- | Force a 'TypeRep' to normal form.
196 rnfTypeRep :: TypeRep -> ()
197 rnfTypeRep = I.rnfSomeTypeRep
198
199
200 -- Keeping backwards-compatibility
201 typeOf1 :: forall t (a :: *). Typeable t => t a -> TypeRep
202 typeOf1 _ = I.someTypeRep (Proxy :: Proxy t)
203
204 typeOf2 :: forall t (a :: *) (b :: *). Typeable t => t a b -> TypeRep
205 typeOf2 _ = I.someTypeRep (Proxy :: Proxy t)
206
207 typeOf3 :: forall t (a :: *) (b :: *) (c :: *). Typeable t
208 => t a b c -> TypeRep
209 typeOf3 _ = I.someTypeRep (Proxy :: Proxy t)
210
211 typeOf4 :: forall t (a :: *) (b :: *) (c :: *) (d :: *). Typeable t
212 => t a b c d -> TypeRep
213 typeOf4 _ = I.someTypeRep (Proxy :: Proxy t)
214
215 typeOf5 :: forall t (a :: *) (b :: *) (c :: *) (d :: *) (e :: *). Typeable t
216 => t a b c d e -> TypeRep
217 typeOf5 _ = I.someTypeRep (Proxy :: Proxy t)
218
219 typeOf6 :: forall t (a :: *) (b :: *) (c :: *) (d :: *) (e :: *) (f :: *).
220 Typeable t => t a b c d e f -> TypeRep
221 typeOf6 _ = I.someTypeRep (Proxy :: Proxy t)
222
223 typeOf7 :: forall t (a :: *) (b :: *) (c :: *) (d :: *) (e :: *) (f :: *)
224 (g :: *). Typeable t => t a b c d e f g -> TypeRep
225 typeOf7 _ = I.someTypeRep (Proxy :: Proxy t)