-- an unsafe cast is guarded by a test for type (representation)
-- equivalence. The module Data.Dynamic uses Typeable for an
-- implementation of dynamics. The module Data.Generics uses Typeable
--- and type-safe cast (but not dynamics) to support the "Scrap your
--- boilerplate" style of generic programming.
+-- and type-safe cast (but not dynamics) to support the \"Scrap your
+-- boilerplate\" style of generic programming.
--
-----------------------------------------------------------------------------
-- * The Typeable class
Typeable( typeOf ), -- :: a -> TypeRep
- -- * Type-safe cast and other clients
+ -- * Type-safe cast
cast, -- :: (Typeable a, Typeable b) => a -> Maybe b
- sameType, -- two type values are the same
+ castss, -- a cast for kind "* -> *"
+ castarr, -- another convenient variation
-- * Type representations
TypeRep, -- abstract, instance of: Eq, Show, Typeable
mkTyCon, -- :: String -> TyCon
mkAppTy, -- :: TyCon -> [TypeRep] -> TypeRep
mkFunTy, -- :: TypeRep -> TypeRep -> TypeRep
- applyTy, -- :: TypeRep -> TypeRep -> Maybe TypeRep
-
- --
- -- let fTy = mkTyCon "Foo" in show (mkAppTy (mkTyCon ",,")
- -- [fTy,fTy,fTy])
- --
- -- returns "(Foo,Foo,Foo)"
- --
- -- The TypeRep Show instance promises to print tuple types
- -- correctly. Tuple type constructors are specified by a
- -- sequence of commas, e.g., (mkTyCon ",,,,") returns
- -- the 5-tuple tycon.
+ applyTy -- :: TypeRep -> TypeRep -> Maybe TypeRep
) where
import qualified Data.HashTable as HT
-import Data.Types
import Data.Maybe
import Data.Either
import Data.Int
--
-------------------------------------------------------------
+
-- | A concrete representation of a (monomorphic) type. 'TypeRep'
-- supports reasonably efficient equality.
data TypeRep = TypeRep !Key TyCon [TypeRep]
#endif
+ --
+ -- let fTy = mkTyCon "Foo" in show (mkAppTy (mkTyCon ",,")
+ -- [fTy,fTy,fTy])
+ --
+ -- returns "(Foo,Foo,Foo)"
+ --
+ -- The TypeRep Show instance promises to print tuple types
+ -- correctly. Tuple type constructors are specified by a
+ -- sequence of commas, e.g., (mkTyCon ",,,,") returns
+ -- the 5-tuple tycon.
----------------- Construction --------------------
-------------------------------------------------------------
--
--- Type-safe cast and other clients
+-- Type-safe cast
--
-------------------------------------------------------------
cast :: (Typeable a, Typeable b) => a -> Maybe b
cast x = r
where
- r = if typeOf x == typeOf (fromJust r) then
- Just (unsafeCoerce x)
- else
- Nothing
+ r = if typeOf x == typeOf (fromJust r)
+ then Just $ unsafeCoerce x
+ else Nothing
--- | Test for type equivalence
-sameType :: (Typeable a, Typeable b) => TypeVal a -> TypeVal b -> Bool
-sameType (_::a->()) (_::b->()) = typeOf (undefined::a) ==
- typeOf (undefined::b)
+-- | A convenient variation for kind "* -> *"
+castss :: (Typeable a, Typeable b) => t a -> Maybe (t b)
+castss x = r
+ where
+ r = if typeOf (get x) == typeOf (get (fromJust r))
+ then Just $ unsafeCoerce x
+ else Nothing
+ get :: t c -> c
+ get = undefined
+
+
+-- | Another variation
+castarr :: (Typeable a, Typeable b, Typeable c, Typeable d)
+ => (a -> t b) -> Maybe (c -> t d)
+castarr x = r
+ where
+ r = if typeOf (get x) == typeOf (get (fromJust r))
+ then Just $ unsafeCoerce x
+ else Nothing
+ get :: (e -> t f) -> (e, f)
+ get = undefined
+
+{-
+
+The variations castss and castarr are arguably not really needed.
+Let's discuss castss in some detail. To get rid of castss, we can
+require "Typeable (t a)" and "Typeable (t b)" rather than just
+"Typeable a" and "Typeable b". In that case, the ordinary cast would
+work. Eventually, all kinds of library instances should become
+Typeable. (There is another potential use of variations as those given
+above. It allows quantification on type constructors.
+
+-}
-------------------------------------------------------------
(typeOf ((undefined :: (a -> b) -> b) f))
+
-------------------------------------------------------
--
-- Generate Typeable instances for standard datatypes
#endif
+
---------------------------------------------
--
-- Internals