-- 
-- (c) Susumu Katayama 2009
--
{-# OPTIONS -XMagicHash -XExistentialQuantification -XPolymorphicComponents #-}
module MagicHaskeller.FakeDynamic(
	Dynamic,
	fromDyn,
	fromDynamic,
	dynApply,
	dynApp,
        dynAppErr,
        dynType,
        unsafeFromDyn, -- :: Dynamic -> a
        unsafeToDyn, -- :: Type -> a -> Dynamic
        aLittleSafeFromDyn -- :: Type -> Dynamic -> a
        -- I (susumu) believe this is enough, provided unsafeFromDyn does not invoke typeOf for type checking. (Otherwise there would be ambiguity error.)
                                 ) where

import Data.Typeable

import GHC.Exts

import MagicHaskeller.Types
import MagicHaskeller.TyConLib
import Control.Monad

infixl `dynApp`

newtype Dynamic = Dynamic (forall a. a)

unsafeFromDyn :: Dynamic -> a
unsafeFromDyn (Dynamic v) = v

unsafeToDyn :: TyConLib -> Type -> a -> e -> Dynamic
unsafeToDyn _ tr a e = Dynamic (unsafeCoerce# a)

aLittleSafeFromDyn :: Type -> Dynamic -> a
aLittleSafeFromDyn _ (Dynamic o) = o

fromDyn :: Typeable a => TyConLib -> Dynamic -> a -> a
fromDyn tcl (Dynamic o) dflt = o
fromDynamic :: MonadPlus m => Type -> Dynamic -> m a
fromDynamic tr (Dynamic o) = return o

instance Show Dynamic where
   showsPrec _ _ = showString "<< FakeDynamic >>"

dynApply :: Dynamic -> Dynamic -> Maybe Dynamic
dynApply f x = Just (dynApp f x)

dynApp :: Dynamic -> Dynamic -> Dynamic
dynApp (Dynamic f) (Dynamic x) = Dynamic ((unsafeCoerce# f) x)
dynAppErr :: String -> Dynamic -> Dynamic -> Dynamic
dynAppErr _ f x = dynApp f x

dynType :: Dynamic -> Type
dynType _ = error "FakeDynamic.dynType: if you want to know the type, use PolyDynamic instead."
