packages feed

open-witness-0.5: src/Data/OpenWitness/Dynamic.hs

-- | This is an approximate re-implementation of "Data.Dynamic" using open witnesses.
module Data.OpenWitness.Dynamic where

import Data.Kind
import Data.OpenWitness.TypeRep
import Data.OpenWitness.Typeable
import Data.Type.Heterogeneous
import Data.Witness
import Prelude

-- * The @Dynamic@ type
type Dynamic = AnyValue TypeRep

-- * Converting to and from @Dynamic@
toDyn ::
       forall (a :: Type). Typeable a
    => a
    -> Dynamic
toDyn = MkAnyValue typeRep

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

fromDynamic ::
       forall (a :: Type). Typeable a
    => Dynamic
    -> Maybe a
fromDynamic (MkAnyValue uq a) = do
    Refl <- testEquality uq (typeRep :: TypeRep a)
    return a

-- * Applying functions of dynamic type
dynApply :: Dynamic -> Dynamic -> Maybe Dynamic
dynApply (MkAnyValue (ApplyTypeRep (ApplyTypeRep repFn' rx') ry) f) (MkAnyValue rx x) = do
    HRefl <- testHetEquality repFn' (typeRep :: TypeRep (->))
    HRefl <- testHetEquality rx' rx
    return (MkAnyValue 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 -> AnyW (TypeRep :: Type -> Type)
dynTypeRep (MkAnyValue r _) = MkAnyW r