c30a43dd6525d7da1fd71ae81e1a25251660d5ce
[ghc.git] / libraries / base / Data / Typeable.hs
1 {-# LANGUAGE Trustworthy #-}
2 {-# LANGUAGE GADTs #-}
3 {-# LANGUAGE NoImplicitPrelude #-}
4 {-# LANGUAGE PolyKinds #-}
5 {-# LANGUAGE ScopedTypeVariables #-}
6 {-# LANGUAGE TypeOperators #-}
7
8 -----------------------------------------------------------------------------
9 -- |
10 -- Module : Data.Typeable
11 -- Copyright : (c) The University of Glasgow, CWI 2001--2004
12 -- License : BSD-style (see the file libraries/base/LICENSE)
13 --
14 -- Maintainer : libraries@haskell.org
15 -- Stability : experimental
16 -- Portability : portable
17 --
18 -- The 'Typeable' class reifies types to some extent by associating type
19 -- representations to types. These type representations can be compared,
20 -- and one can in turn define a type-safe cast operation. To this end,
21 -- an unsafe cast is guarded by a test for type (representation)
22 -- equivalence. The module "Data.Dynamic" uses Typeable for an
23 -- implementation of dynamics. The module "Data.Data" uses Typeable
24 -- and type-safe cast (but not dynamics) to support the \"Scrap your
25 -- boilerplate\" style of generic programming.
26 --
27 -- == Compatibility Notes
28 --
29 -- Since GHC 7.8, 'Typeable' is poly-kinded. The changes required for this might
30 -- break some old programs involving 'Typeable'. More details on this, including
31 -- how to fix your code, can be found on the
32 -- <https://ghc.haskell.org/trac/ghc/wiki/GhcKinds/PolyTypeable PolyTypeable wiki page>
33 --
34 -----------------------------------------------------------------------------
35
36 module Data.Typeable
37 (
38 -- * The Typeable class
39 Typeable,
40 typeRep,
41
42 -- * Propositional equality
43 (:~:)(Refl),
44
45 -- * For backwards compatibility
46 typeOf, typeOf1, typeOf2, typeOf3, typeOf4, typeOf5, typeOf6, typeOf7,
47 Typeable1, Typeable2, Typeable3, Typeable4, Typeable5, Typeable6,
48 Typeable7,
49
50 -- * Type-safe cast
51 cast,
52 eqT,
53 gcast, -- a generalisation of cast
54
55 -- * Generalized casts for higher-order kinds
56 gcast1, -- :: ... => c (t a) -> Maybe (c (t' a))
57 gcast2, -- :: ... => c (t a b) -> Maybe (c (t' a b))
58
59 -- * A canonical proxy type
60 Proxy (..),
61
62 -- * Type representations
63 TypeRep, -- abstract, instance of: Eq, Show, Typeable
64 typeRepFingerprint,
65 rnfTypeRep,
66 showsTypeRep,
67
68 TyCon, -- abstract, instance of: Eq, Show, Typeable
69 tyConFingerprint,
70 tyConString,
71 tyConPackage,
72 tyConModule,
73 tyConName,
74 rnfTyCon,
75
76 -- * Construction of type representations
77 -- mkTyCon, -- :: String -> TyCon
78 mkTyCon3, -- :: String -> String -> String -> TyCon
79 mkTyConApp, -- :: TyCon -> [TypeRep] -> TypeRep
80 mkAppTy, -- :: TypeRep -> TypeRep -> TypeRep
81 mkFunTy, -- :: TypeRep -> TypeRep -> TypeRep
82
83 -- * Observation of type representations
84 splitTyConApp, -- :: TypeRep -> (TyCon, [TypeRep])
85 funResultTy, -- :: TypeRep -> TypeRep -> Maybe TypeRep
86 typeRepTyCon, -- :: TypeRep -> TyCon
87 typeRepArgs, -- :: TypeRep -> [TypeRep]
88 ) where
89
90 import Data.Typeable.Internal hiding (mkTyCon)
91 import Data.Type.Equality
92
93 import Unsafe.Coerce
94 import Data.Maybe
95 import GHC.Base
96
97 -------------------------------------------------------------
98 --
99 -- Type-safe cast
100 --
101 -------------------------------------------------------------
102
103 -- | The type-safe cast operation
104 cast :: forall a b. (Typeable a, Typeable b) => a -> Maybe b
105 cast x = if typeRep (Proxy :: Proxy a) == typeRep (Proxy :: Proxy b)
106 then Just $ unsafeCoerce x
107 else Nothing
108
109 -- | Extract a witness of equality of two types
110 --
111 -- @since 4.7.0.0
112 eqT :: forall a b. (Typeable a, Typeable b) => Maybe (a :~: b)
113 eqT = if typeRep (Proxy :: Proxy a) == typeRep (Proxy :: Proxy b)
114 then Just $ unsafeCoerce Refl
115 else Nothing
116
117 -- | A flexible variation parameterised in a type constructor
118 gcast :: forall a b c. (Typeable a, Typeable b) => c a -> Maybe (c b)
119 gcast x = fmap (\Refl -> x) (eqT :: Maybe (a :~: b))
120
121 -- | Cast over @k1 -> k2@
122 gcast1 :: forall c t t' a. (Typeable t, Typeable t')
123 => c (t a) -> Maybe (c (t' a))
124 gcast1 x = fmap (\Refl -> x) (eqT :: Maybe (t :~: t'))
125
126 -- | Cast over @k1 -> k2 -> k3@
127 gcast2 :: forall c t t' a b. (Typeable t, Typeable t')
128 => c (t a b) -> Maybe (c (t' a b))
129 gcast2 x = fmap (\Refl -> x) (eqT :: Maybe (t :~: t'))
130