2010-12-11 21 views
99

this question के अनुसार, स्कैला की प्रकार प्रणाली Turing complete है। कौन से संसाधन उपलब्ध हैं जो एक नए आने वाले को टाइप-स्तरीय प्रोग्रामिंग की शक्ति का लाभ उठाने में सक्षम बनाता है?स्कैला प्रकार प्रोग्रामिंग संसाधन

यहाँ संसाधनों मैं अब तक मिल गया है कर रहे हैं:

इन संसाधनों महान हैं, लेकिन मुझे लगता है कि मैं याद कर रहा हूँ मूल बातें, और इसलिए एक ठोस नींव नहीं है जिस पर निर्माण करना है। उदाहरण के लिए, परिभाषाओं को टाइप करने के लिए कोई परिचय कहां है? मैं किस प्रकार के संचालन कर सकता हूं?

क्या कोई अच्छा प्रारंभिक संसाधन हैं?

+5

समुदाय विकी? –

+0

व्यक्तिगत रूप से, मुझे लगता है कि कोई भी जो स्कैला में टाइप-स्तरीय प्रोग्रामिंग करना चाहता है, जानता है कि स्कैला में प्रोग्रामिंग को काफी उचित तरीके से कैसे करना है। यहां तक ​​कि यदि इसका मतलब है कि मैं उन लेखों के एक शब्द को समझ नहीं पा रहा हूं जो आपने लिंक किए हैं :-) –

उत्तर

133

अवलोकन

टाइप-स्तरीय प्रोग्रामिंग पारंपरिक, मूल्य स्तर प्रोग्रामिंग के साथ कई समानताएं है। हालांकि, मूल्य-स्तर प्रोग्रामिंग के विपरीत, जहां गणना रनटाइम पर होती है, टाइप-स्तरीय प्रोग्रामिंग में, गणना संकलन समय पर होती है। मैं टाइप-लेवल पर मूल्य-स्तर और प्रोग्रामिंग पर प्रोग्रामिंग के बीच समानांतर आकर्षित करने का प्रयास करूंगा।

मानदंड

प्रकार स्तरीय प्रोग्रामिंग में दो मुख्य मानदंड हैं: "वस्तु उन्मुख" और "कार्यात्मक"। यहां से जुड़े अधिकांश उदाहरण वस्तु-उन्मुख प्रतिमान का पालन करते हैं।

एक अच्छा, वस्तु उन्मुख प्रतिमान में प्रकार स्तरीय प्रोग्रामिंग के काफी सरल उदाहरण apocalisp के implementation of the lambda calculus में पाया जा सकता है, यहाँ दोहराया:

// Abstract trait 
trait Lambda { 
    type subst[U <: Lambda] <: Lambda 
    type apply[U <: Lambda] <: Lambda 
    type eval <: Lambda 
} 

// Implementations 
trait App[S <: Lambda, T <: Lambda] extends Lambda { 
    type subst[U <: Lambda] = App[S#subst[U], T#subst[U]] 
    type apply[U] = Nothing 
    type eval = S#eval#apply[T] 
} 

trait Lam[T <: Lambda] extends Lambda { 
    type subst[U <: Lambda] = Lam[T] 
    type apply[U <: Lambda] = T#subst[U]#eval 
    type eval = Lam[T] 
} 

trait X extends Lambda { 
    type subst[U <: Lambda] = U 
    type apply[U] = Lambda 
    type eval = X 
} 

के रूप में उदाहरण में देखा जा सकता है, वस्तु उन्मुख के रूप में प्रकार स्तरीय प्रोग्रामिंग आय के लिए प्रतिमान इस प्रकार है:

  • पहले: विभिन्न सार प्रकार क्षेत्रों के साथ एक सार विशेषता परिभाषित करते हैं (क्या एक सार क्षेत्र है के लिए नीचे देखें)। यह गारंटी देने के लिए एक टेम्पलेट है कि कार्यान्वयन को मजबूर किए बिना सभी कार्यान्वयन में कुछ प्रकार के फ़ील्ड मौजूद हैं।लैम्ब्डा कैलकुस उदाहरण में, यह trait Lambda से मेल खाता है जो गारंटी देता है कि निम्न प्रकार मौजूद हैं: subst, apply, और eval
  • अगला: subtraits कि सार विशेषता विस्तार को परिभाषित करने और विभिन्न सार प्रकार क्षेत्रों
    • अक्सर, इन subtraits तर्क के साथ parameterized हो जाएगा लागू। लैम्ब्डा पथरी उदाहरण में, उप-प्रकारों trait App extends Lambda जो दो प्रकार के साथ पैरामिट्रीकृत है कर रहे हैं, एक प्रकार (T), और trait X extends Lambda (जो पैरामिट्रीकृत नहीं है) के साथ trait Lam extends Lambda पैरामिट्रीकृत (S और T, दोनों Lambda के उपप्रकार होना चाहिए)।
    • प्रकार फ़ील्ड को अक्सर उप-पथ के प्रकार पैरामीटर और हेश ऑपरेटर के माध्यम से अपने प्रकार के फ़ील्ड का संदर्भ देकर कार्यान्वित किया जाता है: # (जो डॉट ऑपरेटर के समान है: . मानों के लिए)। लैम्ब्डा कैलकुस उदाहरण के App की विशेषता में, प्रकार eval निम्नानुसार कार्यान्वित किया गया है: type eval = S#eval#apply[T]। यह अनिवार्य रूप से eval विशेषता के पैरामीटर S के प्रकार को कॉल कर रहा है, और परिणाम पर T पैरामीटर के साथ apply पर कॉल कर रहा है। नोट, Seval प्रकार होने की गारंटी है क्योंकि पैरामीटर इसे Lambda का उप प्रकार निर्दिष्ट करता है। इसी तरह, eval के परिणाम में apply प्रकार होना चाहिए, क्योंकि यह Lambda का उप प्रकार है, जैसा कि अमूर्त विशेषता Lambda में निर्दिष्ट है।

कार्यात्मक प्रतिमान पैरामिट्रीकृत प्रकार कंस्ट्रक्टर्स कि लक्षण में एक साथ समूहीकृत नहीं कर रहे हैं के बहुत सारे को परिभाषित करने के होते हैं।मूल्य-स्तरीय प्रोग्रामिंग और टाइप-स्तरीय प्रोग्रामिंग के बीच

तुलना

  • abstract class
    • मूल्य का स्तर: abstract class C { val x }
    • प्रकार स्तरीय: trait C { type X }
  • पथ निर्भर प्रकार
    • C.x (संदर्भित फ़ील्ड मान/समारोह वस्तु सी में एक्स)
    • C#x (संदर्भित विशेषता सी में फ़ील्ड प्रकार एक्स)
  • समारोह हस्ताक्षर (कोई कार्यान्वयन)
    • मूल्य स्तर के : def f(x:X) : Y
    • टाइप-लेवल: type f[x <: X] <: Y (इसे "टाइप कंस्ट्रक्टर" कहा जाता है और आमतौर पर सार विशेषता में होता है)
  • समारोह कार्यान्वयन
    • मूल्य का स्तर: def f(x:X) : Y = x
    • प्रकार स्तरीय: type f[x <: X] = x
  • सशर्त,
  • जाँच समानता
    • मूल्य का स्तर: a:A == b:B
    • प्रकार स्तरीय: implicitly[A =:= B]
    • मूल्य का स्तर: कार्यावधि में एक इकाई परीक्षण के माध्यम से JVM में होता है (अर्थात कोई क्रम त्रुटियों): assert(a == b)
  • प्रकार स्तरीय:
    • सार में एक ज़ोर है एक typecheck के माध्यम से संकलक में होता है (यानी कोई संकलक त्रुटियों):
      • सार में एक है प्रकार की तुलना करें: उदाहरण के लिए implicitly[A =:= B]
      • A <:< B, संकलित केवल तभी A, B
      • A =:= B की एक उप-प्रकार है संकलित केवल तभी AB और B की एक उप-प्रकार है A
      • A <%< B की एक उप-प्रकार, ("के रूप में देखा जा सकता है") है संकलित AB (यानीवहाँ B की एक उप-प्रकार को A से एक अंतर्निहित रूपांतरण)
      • an example
      • more comparison operators

प्रकार के बीच परिवर्तित है और महत्व देता

  • के कई में भूतपूर्व गुणों के माध्यम से परिभाषित प्रकार, अक्सर अमूर्त और मुहरबंद दोनों होते हैं, और इसलिए न तो तुरंत और न ही अज्ञात उप-वर्ग के माध्यम से तुरंत चालू किया जा सकता है।

    • उदा: तो यह जब एक मूल्य के स्तर के गणना कर ब्याज की कुछ प्रकार का उपयोग कर एक प्लेसहोल्डर मूल्य के रूप में null उपयोग आम है val x:A = null, जहां A प्रकार है आपके लिए महत्वपूर्ण हैं
  • टाइप-विलोपन के कारण, पैरामिट्रीकृत प्रकार सभी एक ही लग रही है। इसके अलावा, (जैसा कि ऊपर उल्लेख) मान आप के साथ काम कर रहे हैं सभी null हो जाते हैं, और इतने वस्तु प्रकार (उदा एक मैच बयान के माध्यम से) पर कंडीशनिंग अप्रभावी है।

चाल अंतर्निहित कार्यों और मूल्यों का उपयोग करना है। मूल मामला आमतौर पर एक अंतर्निहित मूल्य होता है और रिकर्सिव केस आमतौर पर एक निहित कार्य होता है। दरअसल, टाइप-स्तरीय प्रोग्रामिंग इम्प्लिकेट्स का भारी उपयोग करता है।

sealed trait Nat 
sealed trait _0 extends Nat 
sealed trait Succ[N <: Nat] extends Nat 

यहाँ आप प्राकृतिक संख्या की एक Peano एन्कोडिंग है:

इस उदाहरण (taken from metascala और apocalisp) पर विचार करें। यही है, आपके पास प्रत्येक गैर-ऋणात्मक पूर्णांक के लिए एक प्रकार है: 0 के लिए एक विशेष प्रकार, अर्थात् _0; और शून्य से अधिक प्रत्येक पूर्णांक में Succ[A] का एक प्रकार है, जहां A एक छोटा पूर्णांक का प्रतिनिधित्व करने वाला प्रकार है। उदाहरण के लिए, 2 का प्रतिनिधित्व करने वाला प्रकार होगा: Succ[Succ[_0]] (उत्तराधिकारी शून्य का प्रतिनिधित्व करने वाले प्रकार के लिए दो बार लागू होता है)।

हम और अधिक सुविधाजनक संदर्भ के लिए विभिन्न प्राकृतिक संख्या उर्फ ​​कर सकते हैं। उदाहरण:

type _3 = Succ[Succ[Succ[_0]]] 

अब (। यह एक val को परिभाषित करने के लिए एक समारोह का परिणाम की तरह एक बहुत कुछ है), मान लीजिए हम एक मूल्य के स्तर के समारोह def toInt[T <: Nat](v : T) जो एक तर्क मूल्य में लेता है परिभाषित करना चाहते हैं , v, कि Nat के अनुरूप है और एक पूर्णांक v के प्रकार में इनकोडिंग प्राकृतिक संख्या का प्रतिनिधित्व करने देता है। उदाहरण के लिए, अगर हम मूल्य val x:_3 = null (प्रकार Succ[Succ[Succ[_0]]] की null) है, हम toInt(x) चाहते 3 वापस जाने के लिए होगा।

toInt लागू करने के लिए, हम निम्नलिखित वर्ग का उपयोग करने के लिए जा रहे हैं:

class TypeToValue[T, VT](value : VT) { def getValue() = value } 

के रूप में हम नीचे देखेंगे, एक वस्तु पर निर्भर _0 से प्रत्येक Nat के लिए वर्ग TypeToValue से निर्मित किया जाएगा (उदाहरण के लिए) _3, और प्रत्येक संबंधित प्रकार के मान प्रतिनिधित्व को संग्रहीत करेगा (यानी TypeToValue[_0, Int] मूल्य 0, TypeToValue[Succ[_0], Int] स्टोर करेगा, 1 इत्यादि को संग्रहीत करेगा)। नोट, TypeToValue दो प्रकारों द्वारा पैरामीटर किया गया है: T और VTT उस प्रकार से मेल खाता है जिसे हम मान निर्दिष्ट करने की कोशिश कर रहे हैं (हमारे उदाहरण में, Nat) और VT उस मान के अनुरूप है जिसे हम इसे निर्दिष्ट कर रहे हैं (हमारे उदाहरण में, Int)।

अब हम निम्नलिखित दो अंतर्निहित परिभाषाएँ बनाना:

implicit val _0ToInt = new TypeToValue[_0, Int](0) 
implicit def succToInt[P <: Nat](implicit v : TypeToValue[P, Int]) = 
    new TypeToValue[Succ[P], Int](1 + v.getValue()) 

और हम toInt लागू इस प्रकार है:

def toInt[T <: Nat](v : T)(implicit ttv : TypeToValue[T, Int]) : Int = ttv.getValue() 

को समझने के लिए कैसे toInt काम करता है, के विचार करना क्या यह आदानों की एक जोड़ी पर करता है चलो :

val z:_0 = null 
val y:Succ[_0] = null 

जब हमपर कॉल करते हैं, कंपाइलर ttv प्रकार TypeToValue[_0, Int] (z प्रकार _0) के एक निहित तर्क की तलाश करता है। यह ऑब्जेक्ट _0ToInt पाता है, यह इस ऑब्जेक्ट की getValue विधि को कॉल करता है और 0 वापस ले जाता है। ध्यान देने योग्य महत्वपूर्ण बात यह है कि हमने उस प्रोग्राम को निर्दिष्ट नहीं किया जो उपयोग करने के लिए ऑब्जेक्ट करता है, संकलक इसे पूरी तरह से मिला।

अब toInt(y) पर विचार करें। इस बार, कंपाइलर ttv प्रकार TypeToValue[Succ[_0], Int] (y प्रकार Succ[_0]) के एक निहित तर्क ttv की तलाश करता है। यह फ़ंक्शन succToInt पाता है, जो उपयुक्त प्रकार (TypeToValue[Succ[_0], Int]) का ऑब्जेक्ट वापस कर सकता है और इसका मूल्यांकन करता है। यह फ़ंक्शन स्वयं TypeToValue[_0, Int] (यानी TypeToValue) का एक निहित तर्क (v) लेता है (यानी, TypeToValue जहां पहले प्रकार पैरामीटर में कम Succ[_] है)। कंपाइलर _0ToInt (जैसा ऊपर toInt(z) के मूल्यांकन में किया गया था) की आपूर्ति करता है, और succToInt मूल्य 1 के साथ एक नया TypeToValue ऑब्जेक्ट बनाता है। दोबारा, यह ध्यान रखना महत्वपूर्ण है कि संकलक इन सभी मूल्यों को पूरी तरह से प्रदान कर रहा है, क्योंकि हमारे पास स्पष्ट रूप से उन तक पहुंच नहीं है।

अपने काम की जांच कर रहा

है जिसे आपके प्रकार स्तरीय संगणना कर रहे हैं कि आप क्या उम्मीद सत्यापित करने के लिए कई तरीके हैं। यहां कुछ दृष्टिकोण दिए गए हैं। दो प्रकार A और B बनाएं, जिन्हें आप सत्यापित करना चाहते हैं बराबर हैं।

  • Equal[A, B]
    • साथ:: फिर निम्न संकलन जाँच विशेषता Equal[T1 >: T2 <: T2, T2] (taken from apocolisp)
  • implicitly[A =:= B]

वैकल्पिक रूप से, आप एक मूल्य के प्रकार में बदल सकते हैं (जैसा कि ऊपर दिखाया गया है) और मानों की रनटाइम जांच करें। जैसे assert(toInt(a) == toInt(b)), जहां a प्रकार A और b प्रकार B है।

अतिरिक्त संसाधन

उपलब्ध निर्माणों का पूरा सेट the scala reference manual (pdf) के प्रकार अनुभाग में पाया जा सकता है।

:

Adriaan Moors स्केला से प्रकार निर्माणकर्ता और उदाहरण के साथ संबंधित विषयों के बारे में कई शैक्षिक पेपर है

Apocalisp एक ब्लॉग है जिसमें टाइप-स्तरीय प्रो के कई उदाहरण हैं स्कैला में gramming।

  • Type-Level Programming in Scala कुछ प्रकार-स्तरीय प्रोग्रामिंग जो बूलियन्स, प्राकृतिक संख्या (जैसा कि ऊपर), बाइनरी अंक, विषम सूचियों, और अधिक शामिल हैं का एक शानदार निर्देशित दौरे है।
  • More Scala Typehackery ऊपर लैम्ब्डा कैलकुलेशन कार्यान्वयन है।

ScalaZ एक बहुत ही सक्रिय परियोजना है जो विभिन्न प्रकार-स्तर की प्रोग्रामिंग सुविधाओं का उपयोग करके स्कैला एपीआई को विस्तारित करने वाली कार्यक्षमता प्रदान कर रही है। यह एक बहुत ही रोचक परियोजना है जिसका एक बड़ा अनुसरण है।

MetaScala स्कैला के लिए एक प्रकार-स्तरीय लाइब्रेरी है, जिसमें प्राकृतिक संख्याओं, बूलियन, इकाइयों, एचएलआईस्ट आदि के मेटा प्रकार शामिल हैं। यह Jesper Nordenberg (his blog) द्वारा एक परियोजना है।

:

Michid (blog) कुछ कमाल प्रकार स्तरीय प्रोग्रामिंग के स्काला में (अन्य जवाब से) उदाहरण है

Debasish Ghosh (blog) साथ ही कुछ प्रासंगिक पोस्ट है:

(मैं इस विषय पर कुछ शोध कर रहा हूं और यहां मैंने जो सीखा है। मैं अभी भी नया कर रहा हूँ यह करने के लिए है, इसलिए इस सवाल का जवाब किसी भी अशुद्धियों का कहना है कृपया।)

4

Scalaz में स्रोत कोड, विकी और उदाहरण हैं।

+0

लिंक – iuriisusuk

12

अन्य लिंक यहाँ के अलावा, वहाँ भी स्काला में टाइप स्तर मेटा प्रोग्रामिंग पर मेरे ब्लॉग पोस्ट कर रहे हैं:

+0

नहीं है बस दिलचस्प ब्लॉग के लिए धन्यवाद कहना चाहता था; मैं थोड़ी देर के लिए इसका पालन कर रहा हूं और विशेष रूप से ऊपर वर्णित अंतिम पोस्ट ने महत्वपूर्ण गुणों की मेरी समझ को तेज कर दिया है, एक वस्तु उन्मुख भाषा के लिए एक प्रकार प्रणाली होनी चाहिए। तो धन्यवाद! –

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