-- | This is an approximate re-implementation of "Data.Dynamic" using open witnesses.
module Data.OpenWitness.Dynamic where
{
	import Data.Witness;
	import Data.OpenWitness.Typeable;

	-- * The @Dynamic@ type
	;

	type Dynamic = Any Rep;

	-- * Converting to and from @Dynamic@
	;

	toDyn :: Typeable a => a -> Dynamic;
	toDyn = MkAny rep;

	fromDyn :: Typeable a => Dynamic -> a -> a;
	fromDyn dyn def = case fromDynamic dyn of
	{
		Just a -> a;
		_ -> def;
	};

	fromDynamic :: forall a. Typeable a => Dynamic -> Maybe a;
	fromDynamic (MkAny uq a) = do
	{
		MkEqualType <- matchWitness uq (rep :: Rep a);
		return a;
	};

	-- * Applying functions of dynamic type
	;

	dynApply :: Dynamic -> Dynamic -> Maybe Dynamic;
	dynApply (MkAny (ApplyRep (ApplyRep1 repFn' rx') ry) f) (MkAny rx x) = do
	{
		MkEqualType <- matchRep2 repFn' (rep2 :: Rep2 (->));
		MkEqualType <- matchWitness rx' rx;
		return (MkAny ry (f x));
	};
	dynApply _ _ = Nothing;

	dynApp :: Dynamic -> Dynamic -> Dynamic;
	dynApp a b = case (dynApply a b) of
	{
		Just d -> d;
		_ -> error "Type error in dynamic application.\nCan't apply function to argument";
	};

	dynTypeRep :: Dynamic -> TypeRep;
	dynTypeRep (MkAny r _) = MkAnyWitness r;
}