git.iko.soy/distributed-process
on 425cd78 help sign in
121 lines 4.3 kB history raw
1module Control.Distributed.Static.Internal.Dynamic
2 ( -- * The @Dynamic@ type
3 Dynamic
4 -- * Converting to and from @Dynamic@
5 , toDyn
6 , fromDyn
7 , fromDynamic
8 -- * Applying functions of dynamic type
9 , dynApply
10 , dynApp
11 , dynTypeRep
12 -- * Additions
13 , unsafeToDyn
14 , unsafeCastDyn
15 ) where
17import Control.Exception (Exception)
18import qualified GHC.Prim as GHC (Any)
19import Data.Typeable (Typeable, TypeRep, typeOf, funResultTy)
20import Unsafe.Coerce (unsafeCoerce)
22-------------------------------------------------------------
23--
24-- The type Dynamic
25--
26-------------------------------------------------------------
28{-|
29 A value of type 'Dynamic' is an object encapsulated together with its type.
31 A 'Dynamic' may only represent a monomorphic value; an attempt to
32 create a value of type 'Dynamic' from a polymorphically-typed
33 expression will result in an ambiguity error (see 'toDyn').
35 'Show'ing a value of type 'Dynamic' returns a pretty-printed representation
36 of the object\'s type; useful for debugging.
37-}
38data Dynamic = Dynamic TypeRep Obj
39 deriving Typeable
41instance Show Dynamic where
42 -- the instance just prints the type representation.
43 showsPrec _ (Dynamic t _) =
44 showString "<<" .
45 showsPrec 0 t .
46 showString ">>"
48instance Exception Dynamic
50-- Use GHC's primitive 'Any' type to hold the dynamically typed value.
51--
52-- In GHC's new eval/apply execution model this type must not look
53-- like a data type. If it did, GHC would use the constructor convention
54-- when evaluating it, and this will go wrong if the object is really a
55-- function. Using Any forces GHC to use
56-- a fallback convention for evaluating it that works for all types.
57type Obj = GHC.Any
59-- | Converts an arbitrary value into an object of type 'Dynamic'.
60--
61-- The type of the object must be an instance of 'Typeable', which
62-- ensures that only monomorphically-typed objects may be converted to
63-- 'Dynamic'. To convert a polymorphic object into 'Dynamic', give it
64-- a monomorphic type signature. For example:
65--
66-- > toDyn (id :: Int -> Int)
67--
68toDyn :: Typeable a => a -> Dynamic
69toDyn v = Dynamic (typeOf v) (unsafeCoerce v)
71-- | Converts a 'Dynamic' object back into an ordinary Haskell value of
72-- the correct type. See also 'fromDynamic'.
73fromDyn :: Typeable a
74 => Dynamic -- ^ the dynamically-typed object
75 -> a -- ^ a default value
76 -> a -- ^ returns: the value of the first argument, if
77 -- it has the correct type, otherwise the value of
78 -- the second argument.
79fromDyn (Dynamic t v) def
80 | typeOf def == t = unsafeCoerce v
81 | otherwise = def
83-- | Converts a 'Dynamic' object back into an ordinary Haskell value of
84-- the correct type. See also 'fromDyn'.
85fromDynamic
86 :: Typeable a
87 => Dynamic -- ^ the dynamically-typed object
88 -> Maybe a -- ^ returns: @'Just' a@, if the dynamically-typed
89 -- object has the correct type (and @a@ is its value),
90 -- or 'Nothing' otherwise.
91fromDynamic (Dynamic t v) =
92 case unsafeCoerce v of
93 r | t == typeOf r -> Just r
94 | otherwise -> Nothing
96-- (f::(a->b)) `dynApply` (x::a) = (f a)::b
97dynApply :: Dynamic -> Dynamic -> Maybe Dynamic
98dynApply (Dynamic t1 f) (Dynamic t2 x) =
99 case funResultTy t1 t2 of
100 Just t3 -> Just (Dynamic t3 ((unsafeCoerce f) x))
101 Nothing -> Nothing
103dynApp :: Dynamic -> Dynamic -> Dynamic
104dynApp f x = case dynApply f x of
105 Just r -> r
106 Nothing -> error ("Type error in dynamic application.\n" ++
107 "Can't apply function " ++ show f ++
108 " to argument " ++ show x)
110dynTypeRep :: Dynamic -> TypeRep
111dynTypeRep (Dynamic tr _) = tr
113--------------------------------------------------------------------------------
114-- Additions --
115--------------------------------------------------------------------------------
117unsafeToDyn :: a -> Dynamic
118unsafeToDyn x = Dynamic (error "No type rep") (unsafeCoerce x)
120unsafeCastDyn :: (TypeRep -> TypeRep) -> Dynamic -> Dynamic
121unsafeCastDyn f (Dynamic t x) = Dynamic (f t) x