Generate Typeable info at definition sites
[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 -- For now don't export Module, to avoid name clashes
70 tyConFingerprint,
71 tyConString,
72 tyConPackage,
73 tyConModule,
74 tyConName,
75 rnfTyCon,
76
77 -- * Construction of type representations
78 -- mkTyCon, -- :: String -> TyCon
79 mkTyCon3, -- :: String -> String -> String -> TyCon
80 mkTyConApp, -- :: TyCon -> [TypeRep] -> TypeRep
81 mkAppTy, -- :: TypeRep -> TypeRep -> TypeRep
82 mkFunTy, -- :: TypeRep -> TypeRep -> TypeRep
83
84 -- * Observation of type representations
85 splitTyConApp, -- :: TypeRep -> (TyCon, [TypeRep])
86 funResultTy, -- :: TypeRep -> TypeRep -> Maybe TypeRep
87 typeRepTyCon, -- :: TypeRep -> TyCon
88 typeRepArgs, -- :: TypeRep -> [TypeRep]
89 ) where
90
91 import Data.Typeable.Internal
92 import Data.Type.Equality
93
94 import Unsafe.Coerce
95 import Data.Maybe
96 import GHC.Base
97
98 -------------------------------------------------------------
99 --
100 -- Type-safe cast
101 --
102 -------------------------------------------------------------
103
104 -- | The type-safe cast operation
105 cast :: forall a b. (Typeable a, Typeable b) => a -> Maybe b
106 cast x = if typeRep (Proxy :: Proxy a) == typeRep (Proxy :: Proxy b)
107 then Just $ unsafeCoerce x
108 else Nothing
109
110 -- | Extract a witness of equality of two types
111 --
112 -- @since 4.7.0.0
113 eqT :: forall a b. (Typeable a, Typeable b) => Maybe (a :~: b)
114 eqT = if typeRep (Proxy :: Proxy a) == typeRep (Proxy :: Proxy b)
115 then Just $ unsafeCoerce Refl
116 else Nothing
117
118 -- | A flexible variation parameterised in a type constructor
119 gcast :: forall a b c. (Typeable a, Typeable b) => c a -> Maybe (c b)
120 gcast x = fmap (\Refl -> x) (eqT :: Maybe (a :~: b))
121
122 -- | Cast over @k1 -> k2@
123 gcast1 :: forall c t t' a. (Typeable t, Typeable t')
124 => c (t a) -> Maybe (c (t' a))
125 gcast1 x = fmap (\Refl -> x) (eqT :: Maybe (t :~: t'))
126
127 -- | Cast over @k1 -> k2 -> k3@
128 gcast2 :: forall c t t' a b. (Typeable t, Typeable t')
129 => c (t a b) -> Maybe (c (t' a b))
130 gcast2 x = fmap (\Refl -> x) (eqT :: Maybe (t :~: t'))
131