2017-12-09 85 views
7

पैकेज से Data.Reflection का जीएचसी कार्यान्वयन unsafeCoerce से युक्त एक चाल का उपयोग करता है जो जीएचसी संकलित शब्दकोश का उपयोग कर टाइपक्लास को संकलित करता है। कार्यान्वयन कम है, इसलिए मैं यहाँ अपनी संपूर्णता में यह पुन: पेश कर सकते हैं:क्या डेटा को लागू करना संभव है। प्रतिबिंब की बजाय प्रकार परिवारों का उपयोग करके प्रतिबिंब की चाल?

ghci> reify (42 :: Integer) (\p -> reflect p) :: Integer 
42 

मैं दिलचस्पी थी:

class Reifies s a | s -> a where 
    reflect :: proxy s -> a 

newtype Magic a r = Magic (forall (s :: *). Reifies s a => Proxy s -> r) 

reify :: forall a r. a -> (forall (s :: *). Reifies s a => Proxy s -> r) -> r 
reify a k = unsafeCoerce (Magic k :: Magic a r) (const a) Proxy 

यह यह संभव प्रकार के स्तर पर एक मूल्य वस्तु के बारे में जैसे सोचना है, तो इसे वापस को प्रतिबिंबित करता है इस तकनीक का उपयोग करने में, लेकिन मैंने सोचा कि मेरे उद्देश्यों के लिए एक कार्यात्मक निर्भरता के बजाय Reifies के साथ एक प्रकार के परिवार का उपयोग करना सुविधाजनक होगा, इसलिए मैंने सामान्य परिवर्तन का उपयोग करके कार्यान्वयन को फिर से लिखने का प्रयास किया:

class Reifies s where 
    type Reflects s 
    reflect :: Proxy s -> Reflects s 

newtype Magic a r = Magic (forall (s :: *). (Reifies s, Reflects s ~ a) => Proxy s -> r) 

reify :: forall a r. a -> (forall (s :: *). (Reifies s, Reflects s ~ a) => Proxy s -> r) -> r 
reify a k = unsafeCoerce (Magic k :: Magic a r) (const a) Proxy 

अफसोस की बात है, हालांकि, यह अब काम नहीं करता है! यह unsafeCoerce चाल को तोड़ने के लिए काफी पर्याप्त संकलन परिवर्तन:

ghci> reify (42 :: Integer) (\p -> reflect p) :: Integer 
2199023255808 

हालांकि, मैं कैसे GHC क्यों समझने के लिए काम करता है के साथ पर्याप्त परिचित नहीं हूँ। क्या कार्यात्मक निर्भरता के बजाय संबंधित प्रकार का उपयोग कर Data.Reflection को कार्यान्वित करना संभव है? यदि हां, तो क्या बदलने की जरूरत है? यदि नहीं, तो क्यों नहीं?

उत्तर

6

unsafeCoerce चाल

a -> Proxy s -> r 

के रूप में तथ्य यह है कि

Reifies s a => Proxy s -> r 

रन-टाइम में बिल्कुल वैसा ही प्रतिनिधित्व, है का लाभ लेता है, (Reifies s a, a ~ Reflects s) को बाधा के विस्तार करके, आप इस महत्वपूर्ण का उल्लंघन कल्पना। इसे ठीक करने के कई तरीके हैं। यहाँ एक है:

{-# language MultiParamTypeClasses, TypeFamilies, PolyKinds, KindSignatures, 
     RankNTypes, ScopedTypeVariables, TypeOperators #-} 
module TFReifies where 
import Data.Proxy 
import Unsafe.Coerce 
import Data.Type.Equality 

class Reifies s a where 
    type Reflects s :: * 
    reflect' :: proxy s -> a 

reflect :: (Reifies s a, a ~ Reflects s) => proxy s -> a 
reflect = reflect' 


newtype Magic a r = Magic (forall (s :: *). (Reifies s a) => Proxy s -> r) 

reify' :: forall a r. a -> (forall (s :: *). (Reifies s a) => Proxy s -> r) -> r 
reify' a k = unsafeCoerce (Magic k :: Magic a r) (const a) Proxy 

reify :: forall a r. a -> (forall (s :: *). (Reifies s a, a ~ Reflects s) => Proxy s -> r) -> r 
reify a f = reify' a (\(p :: Proxy s) -> case unsafeCoerce Refl :: a :~: Reflects s of Refl -> f p) 

यहाँ एक संस्करण तुम्हारा के करीब है:

class Reifies s where 
    type Reflects s :: * 
    reflect :: proxy s -> Reflects s 

newtype Magic a r = Magic (forall (s :: *). (Reifies s) => Proxy s -> r) 

reify :: forall a r. a -> (forall (s :: *). (Reifies s, a ~ Reflects s) => Proxy s -> r) -> r 
reify a f = reify' a (\(p :: Proxy s) -> case unsafeCoerce Refl :: a :~: Reflects s of Refl -> f p) 
    where 
    -- This function is totally bogus in other contexts, so we hide it. 
    reify' :: forall a r. a -> (forall (s :: *). (Reifies s) => Proxy s -> r) -> r 
    reify' a k = unsafeCoerce (Magic k :: Magic a r) (const a) Proxy 
+0

के बाद मैं इस सवाल ने लिखा है, मैं मूल में peeked और खोज की है, मेरे आश्चर्य करने के लिए, उस प्रकार समानताओं क्रम गवाहों है , कम से कम कोर स्तर पर। क्या समानता गवाहों के प्रकार के बारे में कुछ जानकारी है? क्या मैं (असुरक्षित) समानता गवाह के स्थान पर कुछ और प्रदान कर सकता हूं? मेरे कोड को 'असुरक्षित कॉमर्स (मैजिक के :: मैजिक ए आर) (कॉन्स ए)() प्रॉक्सी' काम करता है, लेकिन मुझे डर है कि यह हमेशा काम नहीं कर सकता है। –

+0

@AlexisKing, यह एक अच्छा सवाल है जिसके लिए मुझे जवाब नहीं पता है। – dfeuer

+0

@ एलेक्सिसकिंग, एक और विकल्प (मुझे लगता है) 'जीएटीटी' को सबूत देकर 'प्रतिबिंबित' करने के लिए हो सकता है कि 'एक ~ प्रतिबिंबित करता है'। मैंने अभी तक इसके माध्यम से काम नहीं किया है। – dfeuer

संबंधित मुद्दे