यह शायद 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 :: 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()))
यह बहुत आसान हो सकता है अगर base
हमारे लिए apD
, लेकिन यह एक रैंक 2 प्रकार की आवश्यकता है, और Typeable
/Dynamic
की तरह सिर्फ आपूर्ति की कुछ उन से बचने के लिए प्रबंधन, भले ही Data
नहीं करता है।
एक और रास्ता सिर्फ Dynamic
के कार्यान्वयन का दोहन करने के होगा:
data Dynamic = Dynamic TypeRep Any
और unsafeCoerce
अपनी खुद की Dynamic'
डेटा प्रकार के लिए, आप आंतरिक में TypeRep
साथ क्या करने की जरूरत नहीं है, और अपने समारोह लागू करने के बाद , unsafeCoerce
सब कुछ वापस।
स्रोत
2012-06-05 01:16:42
ऐसा लगता है कि 'पॉलीटाइपबल' और 'पॉलीटाइपेबल-यूटिल्स' का उपयोग इस के लिए किया जा सकता है - हालांकि आपको अभी भी सबसे खराब मामले में पूर्ण एकीकरण लागू करना होगा। – Carl