stc-lang-1.0.0: src/Type/Magic/OldGHC.hs
module Type.Magic.OldGHC
( extractList
, injectList
, extractFunctor
, injectFunctor
) where
import Control.Exception
import Data.Dynamic2 (Dynamic(..), TypeCastException(..))
import Data.Typeable
import Unsafe.Coerce
extractFunctor ::
forall f. (Typeable f, Functor f)
=> Dynamic
-> f Dynamic
extractFunctor =
\(Dynamic trl dl) ->
let (tyCon, tyArgs) = splitTyConApp trl
in if tyCon == expectedTyCon
then case tyArgs of
[] ->
error "Constructor must be at least of kind * -> *"
types -> fmap f l
where f = Dynamic $ last types
l = unsafeCoerce dl
_ ->
error $ "Wrong kind for constructor " ++ show tyCon
else throw $ TypeCastException expectedTy (mkTyConApp tyCon [])
where
!expectedTy = typeRep (undefined :: Proxy f)
!expectedTyCon = typeRepTyCon expectedTy
extractList :: Dynamic -> [Dynamic]
extractList = extractFunctor
injectFunctor ::
forall f. (Typeable f, Functor f)
=> Dynamic
-> f Dynamic
-> Dynamic
injectFunctor =
\(Dynamic tra _) l -> Dynamic (mkTy tra) $ unsafeCoerce $ fmap unwrap l
where
unwrap (Dynamic _ v) = v
!targetTyRep = typeRep (undefined :: Proxy f)
!(!con, !args) = splitTyConApp targetTyRep
mkTy tra = mkTyConApp con (args ++ [tra])
injectList :: [Dynamic] -> Dynamic
injectList [] = error "Cannot convert empty list yet"
injectList l@(x:_) = injectFunctor x l