이것은 아마도 sanest 접근 아니지만, 우리는 TypeRep 거짓말 내 reflection
패키지를 남용 할 수 있습니다.
{-# LANGUAGE Rank2Types, FlexibleContexts, ScopedTypeVariables #-}
import Data.Dynamic
import Data.Proxy
import Data.Reflection
import GHC.Prim (Any)
import Unsafe.Coerce
newtype WithRep s a = WithRep { withRep :: a }
instance Reifies s TypeRep => Typeable (WithRep s a) where
typeOf s = reflect (Proxy :: Proxy s)
우리는 지금 우리의 Dynamic
인수의 TypeRep
훔쳐 적절하게 우리의 Dynamic
기능을 인스턴스화 할 수 있음을 감안할 때. 우리 apD
,하지만 그 순위 2 유형을 필요로하고, Typeable
/Dynamic
같은 base
단지 공급 뭔가를 방지하기 위해 관리하는 경우
apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic
apD f a = dynApp df a
where t = dynTypeRep a
df = reify (mkFunTy t (typeOf1 (undefined :: f()) `mkAppTy` t)) $
\(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f()))
그것은 Data
하지 않는 경우에도, 훨씬 더 쉽게 될 수 있습니다.
또 다른 경로가 Dynamic
의 구현 이용 만하는 것입니다 : 당신의 자신의 Dynamic'
데이터 유형에
data Dynamic = Dynamic TypeRep Any
및 unsafeCoerce
, 당신은 내부에있는 TypeRep
와 함께 할 필요가 무엇을하고 기능을 적용한 후 , unsafeCoerce
모든 것.
'polytypeable'과'polytypeable-utils'가이 용도로 사용될 수 있습니다 -하지만 최악의 경우에는 완전한 통합을 구현해야합니다. – Carl