एक तरफ सिंथेटिक सुविधा, सिंगलटन प्रकारों के संयोजन, पथ-निर्भर प्रकार और निहित मूल्यों का अर्थ है कि स्केल को आश्रित टाइपिंग के लिए आश्चर्यजनक रूप से अच्छा समर्थन है, जैसा कि मैंने आकारहीन में प्रदर्शित करने की कोशिश की है ।
आश्रित प्रकारों के लिए स्काला का आंतरिक समर्थन पथ-निर्भर प्रकारों के माध्यम से है । ये एक प्रकार को ऑब्जेक्ट के माध्यम से चयनकर्ता पथ पर निर्भर करने की अनुमति देते हैं- (जैसे। मूल्य-) ग्राफ जैसे,
scala> class Foo { class Bar }
defined class Foo
scala> val foo1 = new Foo
foo1: Foo = Foo@24bc0658
scala> val foo2 = new Foo
foo2: Foo = Foo@6f7f757
scala> implicitly[foo1.Bar =:= foo1.Bar] // OK: equal types
res0: =:=[foo1.Bar,foo1.Bar] = <function1>
scala> implicitly[foo1.Bar =:= foo2.Bar] // Not OK: unequal types
<console>:11: error: Cannot prove that foo1.Bar =:= foo2.Bar.
implicitly[foo1.Bar =:= foo2.Bar]
मेरे विचार में, उपरोक्त प्रश्न का उत्तर देने के लिए पर्याप्त होना चाहिए "क्या स्काला एक भरोसेमंद रूप से टाइप की गई भाषा है?" सकारात्मक में: यह स्पष्ट है कि यहाँ हमारे पास वे प्रकार हैं जो उन मूल्यों से अलग हैं जो उनके उपसर्ग हैं।
हालाँकि, अक्सर इस बात पर आपत्ति जताई जाती है कि स्काला एक "पूरी तरह से" भरोसेमंद प्रकार की भाषा नहीं है, क्योंकि इसमें निर्भर राशि और उत्पाद प्रकार नहीं हैं जैसा कि एजडा या कोक या इदरिस में आंतरिक रूप में पाया जाता है। मुझे लगता है कि यह कुछ हद तक बुनियादी बातों के रूप में एक निर्धारण को दर्शाता है, फिर भी, मैं कोशिश करूँगा और दिखाऊंगा कि स्केला इन अन्य भाषाओं की तुलना में बहुत करीब है, आमतौर पर स्वीकार किया जाता है।
शब्दावली के बावजूद, निर्भर योग प्रकार (जिसे सिग्मा प्रकार के रूप में भी जाना जाता है) बस मूल्यों की एक जोड़ी है जहां दूसरे मूल्य का प्रकार पहले मूल्य पर निर्भर है। यह सीधे स्काला में प्रतिनिधित्व करने योग्य है,
scala> trait Sigma {
| val foo: Foo
| val bar: foo.Bar
| }
defined trait Sigma
scala> val sigma = new Sigma {
| val foo = foo1
| val bar = new foo.Bar
| }
sigma: java.lang.Object with Sigma{val bar: this.foo.Bar} = $anon$1@e3fabd8
और वास्तव में, यह आश्रित विधि प्रकारों के एन्कोडिंग का एक महत्वपूर्ण हिस्सा है, जो 2.10 से पहले स्काला में 'बेकरी ऑफ डूम' से बचने के लिए आवश्यक है (या पहले प्रायोगिक-योध् य-विधि प्रकार स्काला संकलक विकल्प के माध्यम से)।
आश्रित उत्पाद प्रकार (उर्फ पाई प्रकार) अनिवार्य रूप से मूल्यों से प्रकारों के कार्य हैं। वे वैचारिक रूप से टाइप की गई प्रोग्रामिंग भाषाओं के लिए वैधानिक रूप से आकार वाले वैक्टर और अन्य पोस्टर बच्चों के प्रतिनिधित्व के लिए महत्वपूर्ण हैं। हम पथ पर निर्भर प्रकारों, सिंगलटन प्रकारों और अंतर्निहित मापदंडों के संयोजन का उपयोग करके पिया को एनकोड कर सकते हैं। पहले हम एक विशेषता को परिभाषित करते हैं जो कि टाइप T के मान से एक प्रकार U,
scala> trait Pi[T] { type U }
defined trait Pi
हम एक बहुरूपिक विधि को परिभाषित कर सकते हैं जो इस प्रकार का उपयोग करता है,
scala> def depList[T](t: T)(implicit pi: Pi[T]): List[pi.U] = Nil
depList: [T](t: T)(implicit pi: Pi[T])List[pi.U]
( pi.U
परिणाम प्रकार में पथ-निर्भर प्रकार के उपयोग पर ध्यान दें List[pi.U]
)। प्रकार T के मान को देखते हुए, यह फ़ंक्शन उस विशेष T मान के अनुरूप प्रकार के मानों की एक (n खाली) सूची लौटाएगा।
आइए अब कुछ कार्यात्मक मूल्यों और निहित गवाहों को परिभाषित करते हैं जो कार्यात्मक संबंधों को हम पकड़ना चाहते हैं,
scala> object Foo
defined module Foo
scala> object Bar
defined module Bar
scala> implicit val fooInt = new Pi[Foo.type] { type U = Int }
fooInt: java.lang.Object with Pi[Foo.type]{type U = Int} = $anon$1@60681a11
scala> implicit val barString = new Pi[Bar.type] { type U = String }
barString: java.lang.Object with Pi[Bar.type]{type U = String} = $anon$1@187602ae
और अब यहाँ क्रिया में हमारा पाई-टाइप-उपयोग फ़ंक्शन है,
scala> depList(Foo)
res2: List[fooInt.U] = List()
scala> depList(Bar)
res3: List[barString.U] = List()
scala> implicitly[res2.type <:< List[Int]]
res4: <:<[res2.type,List[Int]] = <function1>
scala> implicitly[res2.type <:< List[String]]
<console>:19: error: Cannot prove that res2.type <:< List[String].
implicitly[res2.type <:< List[String]]
^
scala> implicitly[res3.type <:< List[String]]
res6: <:<[res3.type,List[String]] = <function1>
scala> implicitly[res3.type <:< List[Int]]
<console>:19: error: Cannot prove that res3.type <:< List[Int].
implicitly[res3.type <:< List[Int]]
(ध्यान दें कि यहाँ हम स्काला का उपयोग करने <:<
के बजाय उप-प्रकार-साक्षी ऑपरेटर =:=
क्योंकि res2.type
और res3.type
सिंगलटन प्रकार और प्रकार हम आरएचएस पर पुष्टि कर रहे हैं की तुलना में इसलिए अधिक सटीक हैं)।
व्यवहार में, हालांकि, स्काला में हम सिग्मा और पाई प्रकार एन्कोडिंग द्वारा शुरू नहीं करेंगे और फिर वहां से आगे बढ़ेंगे जैसा कि हम एजडा या इदरीस में करेंगे। इसके बजाय हम सीधे पथ-निर्भर प्रकारों, सिंगलटन प्रकारों और ध्वनियों का उपयोग करेंगे। आप इस बात के कई उदाहरण पा सकते हैं कि यह आकारहीन कैसे होता है: आकार प्रकार , एक्स्टेंसिबल रिकॉर्ड , व्यापक एचएलिस्ट , अपने बॉयलरप्लेट , जेनेरिक जिपर इत्यादि को स्क्रैप करें ।
केवल शेष आपत्ति मैं देख सकता हूं कि पाई प्रकारों के उपरोक्त एन्कोडिंग में हमें अभिव्यंजक होने के लिए निर्भरता वाले मूल्यों के सिंगलटन प्रकार की आवश्यकता होती है। दुर्भाग्य से स्काला में यह केवल संदर्भ प्रकारों के मानों के लिए ही संभव है, न कि गैर-संदर्भ प्रकारों के मूल्यों के लिए (एस्प। उदाहरण। इंट)। यह शर्म की बात है, लेकिन नहीं एक आंतरिक कठिनाई है: स्काला के प्रकार चेकर आंतरिक रूप से गैर संदर्भ मूल्यों की सिंगलटन प्रकार का प्रतिनिधित्व करता है, और एक किए गए हैं जोड़ी के प्रयोगों उन्हें सीधे व्यक्त करने में। व्यवहार में हम प्राकृतिक संख्याओं के काफी मानक प्रकार-स्तरीय एन्कोडिंग के साथ समस्या के आसपास काम कर सकते हैं ।
किसी भी स्थिति में, मुझे नहीं लगता कि इस मामूली डोमेन प्रतिबंध को स्केला की स्थिति के लिए आपत्तिजनक रूप से टाइप की गई भाषा के रूप में इस्तेमाल किया जा सकता है। यदि ऐसा है, तो डिपेंडेंट एमएल (जो केवल प्राकृतिक संख्या मूल्यों पर निर्भरता की अनुमति देता है) के लिए वही कहा जा सकता है जो एक विचित्र निष्कर्ष होगा।