[project @ 2003-07-28 15:03:05 by panne]
[haskell-directory.git] / Data / Typeable.hs
index 3ed5850..6f38656 100644 (file)
@@ -15,8 +15,8 @@
 -- 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.
 --
 -----------------------------------------------------------------------------
 
@@ -26,9 +26,10 @@ module Data.Typeable
        -- * 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
@@ -38,24 +39,12 @@ module Data.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
@@ -101,6 +90,7 @@ import NHC.IOExtras (IORef,newIORef,readIORef,writeIORef,unsafePerformIO)
 --
 -------------------------------------------------------------
 
+
 -- | A concrete representation of a (monomorphic) type.  'TypeRep'
 -- supports reasonably efficient equality.
 data TypeRep = TypeRep !Key TyCon [TypeRep] 
@@ -118,6 +108,16 @@ instance Eq TyCon where
 
 #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 --------------------
 
@@ -228,7 +228,7 @@ class Typeable a where
 
 -------------------------------------------------------------
 --
---             Type-safe cast and other clients
+--             Type-safe cast
 --
 -------------------------------------------------------------
 
@@ -236,16 +236,44 @@ class Typeable a where
 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.
+
+-}
 
 
 -------------------------------------------------------------
@@ -315,6 +343,7 @@ instance (Typeable a, Typeable b) => Typeable (a -> b) where
                     (typeOf ((undefined :: (a -> b) -> b) f))
 
 
+
 -------------------------------------------------------
 --
 -- Generate Typeable instances for standard datatypes
@@ -354,6 +383,7 @@ INSTANCE_TYPEABLE1(IORef,ioRefTc,"IORef")
 #endif
 
 
+
 ---------------------------------------------
 --
 --             Internals