सरल उपाय
आपका सबसे अच्छा शर्त जब पथ पर निर्भर प्रकार के साथ काम कर हमेशा के आसपास के मालिक मूल्य रखने के लिए, क्योंकि स्काला अन्यथा बहुत ही सीमित अनुमान और तर्क शक्ति है है।
Platform.parse("ios") flatMap {
p => p.parseArch("arm64").map(exec(p))
}
यह rewritings प्रदर्शन करने के लिए आम तौर पर संभव है, हालांकि कोड अक्सर कम संक्षिप्त और सुरुचिपूर्ण हो जाएगा:
उदाहरण के लिए, अपने कोड उदाहरण के रूप में फिर से लिखा जा सकता है। एक आम अभ्यास निर्भर कार्यों और पैरामीट्रिक कक्षाओं का उपयोग करना है।
निर्भर प्रकार
अपने उदाहरण में, कोड का उपयोग करना:
Platform.parse("ios").flatMap(p => p.parseArch("arm64").map(a => (p, a)))
टाइप Option[(Platform, Platform#Arch)]
, क्योंकि स्काला का अनुमान इस तथ्य है कि टपल के दूसरे तत्व पहले तत्व पर निर्भर है बनाए रखने नहीं कर सकता है। (आपको A$A2.this.Platform
मिलता है क्योंकि आपने कुछ आंतरिक संदर्भ में Platform
घोषित किया है।)
दूसरे शब्दों में, स्कैला का Tuple2
प्रकार निर्भर नहीं है। हम सही कर सकते हैं कि हमारे अपने वर्ग बनाकर:
case class DepPair(p: Platform)(a: p.Arch)
हालांकि, स्काला निर्भर वर्ग हस्ताक्षर अभी तक का समर्थन नहीं करता है, और यह संकलन नहीं होंगे। val plat
और val arch
पर
trait Dep {
val plat: Platform
val arch: plat.Arch
}
Platform.parse("ios")
.flatMap { p => p.parseArch("arm64").map { a =>
new Dep { val plat: p.type = p; val arch: p.Arch = a }}}
.flatMap { dep => exec(dep.plat)(dep.arch) }
सूचना ascriptions, उनके बिना के रूप में, स्काला एक परिष्कृत प्रकार प्रकार-जाँच विफल कर देगा कि उसका अनुमान लगा करने की कोशिश करेंगे: इसके बजाय, हम एक विशेषता का उपयोग करने के लिए सेट करें।
हम वास्तव में स्कैला (आईएमएचओ) में क्या करना उचित है इसकी सीमा पर हैं। उदाहरण के लिए, अगर हमने trait Dep[P <: Platform]
पर parametrized किया था, तो हम सभी प्रकार की समस्याओं में मिल गया होगा।विशेष रूप से:
Error:(98, 15) type mismatch;
found : Platform => Option[Dep[p.type]] forSome { val p: Platform }
required: Platform => Option[B]
स्काला एक अस्तित्व समारोह प्रकार infers, लेकिन क्या हम वास्तव में चाहते हैं समारोह प्रकार के अंदर अस्तित्व मात्रा है। हम स्काला कि समझने के लिए मार्गदर्शन करने के है, और हम की तरह कुछ के साथ अंत: मालिक val
चारों ओर (सरल उपाय), या जोखिम के साथ चिपके रहते हैं:
Platform.parse("ios").flatMap[Dep[p.type] forSome { val p: Platform }]{
case p => p.parseArch("arm64").map{case a: p.Arch =>
new Dep[p.type] { val plat: p.type = p; val arch = a }}}
.flatMap { dep => exec(dep.plat)(dep.arch) }
अब मैं आप तय करते हैं जो तरीका सबसे अच्छा है दूँगा आपके द्वारा छोड़ी गई स्वच्छता की किसी भी भावना को खोना!
लेकिन विवेक और existentials खोने के बारे में बात कर रही है, चलो कोशिश करते हैं और एक सा आगे की जांच करते हैं ...
का उपयोग existentials (विफल)
अपने कोड में मध्यवर्ती परिणाम के समस्याग्रस्त प्रकार Option[(Platform, Platform#Arch)]
था। वास्तव में यह बेहतर व्यक्त करने के लिए, एक अस्तित्व का उपयोग कर के रूप में एक तरीका है:
Option[(p.type, p.Arch) forSome {val p: Platform}]
हम यह स्पष्ट रूप से निर्दिष्ट द्वारा स्काला मदद कर सकते हैं, तो मध्यवर्ती परिणाम इच्छित प्रकार का है:
val tmp: Option[(p.type, p.Arch) forSome {val p: Platform}] =
Platform.parse("ios")
.flatMap { case p => p.parseArch("arm64").map { a => (p, a): (p.type, p.Arch) }}
हालांकि, अब हम स्कैला के प्रकार प्रणाली के एक बहुत ही संवेदनशील क्षेत्र को छूते हैं, और यह अक्सर समस्याओं का कारण बनता है। वास्तव में, मैं दूसरी flatMap
व्यक्त करने के लिए एक तरह से नहीं मिला ...
कोशिश कर रहा tmp.flatMap { case (p, a) => exec(p)(a) }
बहुत उपयोगी देता है:
Error:(30, 30) type mismatch;
found : a.type (with underlying type p.Arch)
required: p.Arch
एक और परीक्षण:
tmp.flatMap {
(tup: (p.type, p.Arch) forSome {val p: Platform}) => exec(tup._1)(tup._2)
}
Error:(32, 79) type mismatch;
found : tup._2.type (with underlying type p.Arch)
required: tup._1.Arch
इस पर बिंदु, मुझे लगता है कि कोई भी उचित व्यक्ति हार जाएगा - और शायद कुछ दिनों के लिए स्कैला प्रोग्रामिंग से दूर रहें ;-)
इंटरस्टिंग। मुझे लगता है कि पथ-निर्भर प्रकार अभी भी स्केल में किनारों के चारों ओर काफी मोटा है। अपना जवाब पढ़ने के बाद, मैंने उन्हें टुपल्स में पास करने के लिए छोड़ दिया है ('विशेषता 'समाधान दिलचस्प है लेकिन थोड़ा भी वर्बोज़ है) और इसके बजाय नीचे दिखाए गए बाहरी गुण के संदर्भ में आंतरिक विशेषता बना दी गई है। मेरे संदेहों को मंजूरी देने के लिए धन्यवाद। –
ग्रेट। ध्यान दें कि आप अपना 'वैल प्लेटफ़ॉर्म' एक 'डीफ़ प्लेटफॉर्म' बना सकते हैं, इसलिए आपको बाहरी विशेषता में अतिरिक्त पॉइंटर रखना नहीं है (स्कैला पहले ही आंतरिक लक्षणों में बाहरी लक्षणों के लिए पॉइंटर्स स्टोर करता है)। –
'def' और 'val' शामिल पॉइंटर के बीच का अंतर नहीं पता था। 'Def' को समान रूप से पॉइंटर बनाने के लिए जो कुछ भी संदर्भित करता है उसे _closure_ में नहीं दिखाएगा (सुनिश्चित नहीं है कि यह स्केल में एक चीज़ है या नहीं)? शायद आप एक लिंक साझा कर सकते हैं? –