2015-06-01 6 views
6

मैं अपने सिर को जीएचसी एक्सटेंशन KindSignatures और DataKinds के आसपास लपेटने की कोशिश कर रहा हूं। Data.Modular पैकेज को देखते हुए, मैं समझता हूँ कि मोटे तौर पर कि'जीएचसी.TypeLits' को समझना

newtype i `Mod` (n :: Nat) = Mod i deriving (Eq, Ord) 

प्रकार का C++ टेम्पलेट <typename T, int N> (निर्माता प्रकार T का केवल एक ही तर्क लेने के साथ) घोषित करने के बराबर है। हालांकि, GHC.TypeLits पैकेज को देखते हुए, मुझे जो कुछ हो रहा है, उसे समझ में नहीं आता है। इस पैकेज के बारे में कोई सामान्य स्पष्टीकरण सहायक होगा। इससे पहले इस सवाल का विषय बंद के रूप में यद्यपि चिह्नित किया जाता है, यहाँ कुछ विशिष्ट उप-प्रश्न हैं:

  • एक KnownNat वर्ग इसकी सूचना देने के प्रकार से प्रकार चर निकालने, समझ में आता है के लिए आवश्यक कार्य के साथ, लेकिन natVal क्या करना होता है, और proxy टाइप वैरिएबल क्या है?
  • आप someNatVal कहां उपयोग करेंगे?
  • अंत में, SomeNat क्या है - एक प्रकार का स्तर संख्या अज्ञात कैसे हो सकती है? एक प्रकार के स्तर की संख्या का पूरा बिंदु नहीं है कि संकलन समय पर ज्ञात है?
+1

नहीं, सभी को संकलन समय पर सभी को जाना नहीं है। उदाहरण के लिए, 'id' संकलित करते समय यह ज्ञात नहीं है कि सभी संभावित तर्क क्या होंगे। – augustss

+0

@augustss अच्छा बिंदु, लेकिन फिर 'SomeNat' का उद्देश्य क्या है? – Alec

+1

यह अस्तित्व में प्रमाणित प्रकार के लिए एक प्रकार है। आप जानते हैं कि यह तरह का नेट है, लेकिन वास्तव में किस प्रकार का नहीं है। – augustss

उत्तर

2

यह प्रश्न काफी व्यापक है - मैं केवल कुछ बिंदुओं को संबोधित करूंगा।

proxy टाइप वैरिएबल * -> * की तरह एक प्रकार का चर है, यानी प्रकार के प्रकार के रचनाकार। व्यावहारिक रूप से, यदि आपके पास कोई फ़ंक्शन

foo :: proxy a -> ... 

आप इसे प्रकार के मानों को पास कर सकते हैं उदा। Maybe Int, proxy = Maybe और a = Int चुनना। आप [] Char के प्रकार भी मान सकते हैं ([Char] के रूप में भी लिखा गया है)। या, और अधिक सामान्यतः, प्रकार Proxy Int, के एक मूल्य जहां Proxy रूप

data Proxy a = Proxy 

एक डेटा प्रकार है जो किसी भी रन-टाइम जानकारी नहीं होता यानी परिभाषित डेटा प्रकार है (इसके लिए एक भी मूल्य है!), लेकिन जिसमें संकलन-समय की जानकारी होती है (प्रेत प्रकार परिवर्तनीय a)।

मान लें N एक प्रकार का प्रकार Nat - एक संकलित समय प्राकृतिक है। हम एक समारोह

bar :: N -> ... 

लिख सकते हैं, लेकिन यह बुला हमें प्रकार N के एक मूल्य के निर्माण के लिए की आवश्यकता होगी - जो सारहीन है। टाइप N का उद्देश्य संकलन-समय की जानकारी लेना है, केवल, और इसके रन-टाइम मान ऐसी चीजें नहीं हैं जिन्हें हम वास्तव में उपयोग करना चाहते हैं। वास्तव में, N के पास नीचे के अलावा, कोई मूल्य नहीं हो सकता है। हम सकता है कॉल

bar (undefined :: N) 

लेकिन यह अजीब लग रहा है। इसे पढ़ते हुए, हमें यह समझना होगा कि bar अपने पहले तर्क में आलसी है और इससे इसका उपयोग करने की कोशिश करने का विचलन नहीं होगा। समस्या यह है कि bar :: N -> ... प्रकार हस्ताक्षर भ्रामक है: यह दावा करता है कि परिणाम N के तर्क के मान पर निर्भर हो सकता है, जब यह वास्तव में मामला नहीं है।इसके बजाय, अगर हम

baz :: Proxy N -> ... 

का उपयोग आशय स्पष्ट है - वहाँ उस के लिए केवल एक ही रन-टाइम मूल्य है: Proxy :: Proxy N। यह समान रूप से स्पष्ट है कि N मान संकलन समय पर ही मौजूद है।

कभी कभी, बजाय विशिष्ट Proxy N का उपयोग कर के, कोड थोड़ा

foo :: proxy N -> ... 

जो एक ही लक्ष्य को प्राप्त करने के सिलसिले में, लेकिन परमिट भी अलग Proxy प्रकार है। (व्यक्तिगत रूप से, मैं इस सामान्यीकरण से बहुत रोमांचित नहीं हूं।)

प्रश्न पर वापस जाएं: natVal एक ऐसा फ़ंक्शन है जो एक संकलन-समय को केवल रन-टाइम मान में प्राकृतिक बनाता है। अर्थात। यह Proxy N को Int में परिवर्तित करता है, जो केवल निरंतर लौटता है।

यदि आप टाइप टेम्पलेट तर्कों को मॉडल संकलन समय नैसर्गिक के लिए उपयोग करते हैं तो आप सी ++ टेम्पलेट्स के साथ समानता प्राप्त कर सकते हैं। जैसे

template <typename N> struct S { using pred = N; }; 
struct Z {}; 

template <typename N> int natVal(); 
template <typename N> int natVal() { return 1 + natVal<typename N::pred>(); } 
template <>   int natVal<Z>() { return 0; } 

int main() { 
    cout << natVal<S<S<Z>>>() << endl; // outputs 2 
    return 0; 
} 

बस बहाना S और Z के लिए कोई सार्वजनिक कंस्ट्रक्टर्स देखते हैं: उनके रन-टाइम मूल्यों महत्वहीन, केवल अपने संकलन समय जानकारी मामला नहीं है।

+1

प्रॉक्सी के उपयोग के लिए एक महत्वपूर्ण कारण यह है कि टाइप-स्तरीय 'ए' जिसे आप पास करने का प्रयास कर रहे हैं, उसमें '* 'प्रकार नहीं हो सकता है। उदाहरण के लिए, 'प्रॉक्सी 3 -> बी' अच्छी तरह से दयालु है, लेकिन '3 -> बी' नहीं है; प्रॉक्सी हो सकता है -> बी' अच्छी तरह से दयालु है, लेकिन 'शायद -> बी' नहीं है। –

+0

@ एंटल्स-जेड मैं देखता हूं, धन्यवाद। – chi

+1

इसके अलावा, 'अनिर्धारित :: एन' केवल अच्छी तरह से दयालु है अगर एन दयालु है *। – augustss

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