यह प्रश्न काफी व्यापक है - मैं केवल कुछ बिंदुओं को संबोधित करूंगा।
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
के लिए कोई सार्वजनिक कंस्ट्रक्टर्स देखते हैं: उनके रन-टाइम मूल्यों महत्वहीन, केवल अपने संकलन समय जानकारी मामला नहीं है।
नहीं, सभी को संकलन समय पर सभी को जाना नहीं है। उदाहरण के लिए, 'id' संकलित करते समय यह ज्ञात नहीं है कि सभी संभावित तर्क क्या होंगे। – augustss
@augustss अच्छा बिंदु, लेकिन फिर 'SomeNat' का उद्देश्य क्या है? – Alec
यह अस्तित्व में प्रमाणित प्रकार के लिए एक प्रकार है। आप जानते हैं कि यह तरह का नेट है, लेकिन वास्तव में किस प्रकार का नहीं है। – augustss