1 {-# LANGUAGE CPP, NoImplicitPrelude #-}
3 -----------------------------------------------------------------------------
5 -- Module : Data.Dynamic
6 -- Copyright : (c) The University of Glasgow 2001
7 -- License : BSD-style (see the file libraries/base/LICENSE)
9 -- Maintainer : libraries@haskell.org
10 -- Stability : experimental
11 -- Portability : portable
13 -- The Dynamic interface provides basic support for dynamic types.
15 -- Operations for injecting values of arbitrary type into
16 -- a dynamically typed value, Dynamic, are provided, together
17 -- with operations for converting dynamic values into a concrete
18 -- (monomorphic) type.
20 -----------------------------------------------------------------------------
25 -- Module Data.Typeable re-exported for convenience
28 -- * The @Dynamic@ type
29 Dynamic, -- abstract, instance of: Show, Typeable
31 -- * Converting to and from @Dynamic@
32 toDyn, -- :: Typeable a => a -> Dynamic
33 fromDyn, -- :: Typeable a => Dynamic -> a -> a
34 fromDynamic, -- :: Typeable a => Dynamic -> Maybe a
36 -- * Applying functions of dynamic type
48 #ifdef __GLASGOW_HASKELL__
62 import NHC.IOExtras (IORef,newIORef,readIORef,writeIORef,unsafePerformIO)
67 -------------------------------------------------------------
71 -------------------------------------------------------------
74 A value of type 'Dynamic' is an object encapsulated together with its type.
76 A 'Dynamic' may only represent a monomorphic value; an attempt to
77 create a value of type 'Dynamic' from a polymorphically-typed
78 expression will result in an ambiguity error (see 'toDyn').
80 'Show'ing a value of type 'Dynamic' returns a pretty-printed representation
81 of the object\'s type; useful for debugging.
84 data Dynamic = Dynamic TypeRep Obj
87 INSTANCE_TYPEABLE0(Dynamic,dynamicTc,"Dynamic")
89 instance Show Dynamic where
90 -- the instance just prints the type representation.
91 showsPrec _ (Dynamic t _) =
96 #ifdef __GLASGOW_HASKELL__
97 -- here so that it isn't an orphan:
98 instance Exception Dynamic
101 #ifdef __GLASGOW_HASKELL__
103 -- Use GHC's primitive 'Any' type to hold the dynamically typed value.
105 -- In GHC's new eval/apply execution model this type must not look
106 -- like a data type. If it did, GHC would use the constructor convention
107 -- when evaluating it, and this will go wrong if the object is really a
108 -- function. Using Any forces GHC to use
109 -- a fallback convention for evaluating it that works for all types.
110 #elif !defined(__HUGS__)
114 -- | Converts an arbitrary value into an object of type 'Dynamic'.
116 -- The type of the object must be an instance of 'Typeable', which
117 -- ensures that only monomorphically-typed objects may be converted to
118 -- 'Dynamic'. To convert a polymorphic object into 'Dynamic', give it
119 -- a monomorphic type signature. For example:
121 -- > toDyn (id :: Int -> Int)
123 toDyn :: Typeable a => a -> Dynamic
124 toDyn v = Dynamic (typeOf v) (unsafeCoerce v)
126 -- | Converts a 'Dynamic' object back into an ordinary Haskell value of
127 -- the correct type. See also 'fromDynamic'.
128 fromDyn :: Typeable a
129 => Dynamic -- ^ the dynamically-typed object
130 -> a -- ^ a default value
131 -> a -- ^ returns: the value of the first argument, if
132 -- it has the correct type, otherwise the value of
133 -- the second argument.
134 fromDyn (Dynamic t v) def
135 | typeOf def == t = unsafeCoerce v
138 -- | Converts a 'Dynamic' object back into an ordinary Haskell value of
139 -- the correct type. See also 'fromDyn'.
142 => Dynamic -- ^ the dynamically-typed object
143 -> Maybe a -- ^ returns: @'Just' a@, if the dynamically-typed
144 -- object has the correct type (and @a@ is its value),
145 -- or 'Nothing' otherwise.
146 fromDynamic (Dynamic t v) =
147 case unsafeCoerce v of
148 r | t == typeOf r -> Just r
149 | otherwise -> Nothing
151 -- (f::(a->b)) `dynApply` (x::a) = (f a)::b
152 dynApply :: Dynamic -> Dynamic -> Maybe Dynamic
153 dynApply (Dynamic t1 f) (Dynamic t2 x) =
154 case funResultTy t1 t2 of
155 Just t3 -> Just (Dynamic t3 ((unsafeCoerce f) x))
158 dynApp :: Dynamic -> Dynamic -> Dynamic
159 dynApp f x = case dynApply f x of
161 Nothing -> error ("Type error in dynamic application.\n" ++
162 "Can't apply function " ++ show f ++
163 " to argument " ++ show x)
165 dynTypeRep :: Dynamic -> TypeRep
166 dynTypeRep (Dynamic tr _) = tr