content: module Data.Dynamic(
    Typeable(..),
    Dynamic,
    toDyn,
    fromDyn, fromDynamic,
    dynApply, dynApp,
    dynTypeRep,
    ) where
  import Prelude
  import Data.Maybe
  import Data.Proxy
  import Data.Typeable
  import Unsafe.Coerce
  import Control.Exception
  
  data Dynamic = D TypeRep AnyType
    deriving Typeable
  
  instance Exception Dynamic
  
  instance Show Dynamic where
    show (D t _) = "<<" ++ show t ++ ">>"
  
  toDyn :: forall a . Typeable a => a -> Dynamic
  toDyn a = D (typeOf a) (unsafeCoerce a)
  
  fromDyn :: forall a . Typeable a => Dynamic -> a -> a
  fromDyn d a = fromMaybe a $ fromDynamic d
  
  fromDynamic :: forall a . Typeable a => Dynamic -> Maybe a
  fromDynamic (D tr a) | tr == typeRep (Proxy :: Proxy a) = Just (unsafeCoerce a)
                       | otherwise = Nothing
  
  dynApp :: Dynamic -> Dynamic -> Dynamic
  dynApp f a = fromMaybe (error "Dynamic.dynApp") $ dynApply f a
  
  dynApply :: Dynamic -> Dynamic -> Maybe Dynamic
  dynApply (D ftr f) (D atr a) = g <$> funResultTy ftr atr
    where g rtr = D rtr (unsafeCoerce f a)
  
  dynTypeRep :: Dynamic -> TypeRep
  dynTypeRep (D tr _) = tr
  