2013-02-06 101 views
11

मुझे स्कैला को एक प्रकार प्रक्षेपण से सही प्रकार का अनुमान लगाने के लिए कुछ परेशानी होती है।प्रक्षेपण प्रकार से सही प्रकार पैरामीटर का अनुमान कैसे लगाएं?

निम्नलिखित पर विचार करें:

trait Foo { 
    type X 
} 

trait Bar extends Foo { 
    type X = String 
} 

def baz[F <: Foo](x: F#X): Unit = ??? 

उसके बाद निम्न ठीक संकलित:

val x: Foo#X = ???  
baz(x) 

लेकिन निम्नलिखित संकलन नहीं होगा:

val x: Bar#X = ???  
baz(x) 

स्काला "अंतर्निहित प्रकार स्ट्रिंग देखता है "x के लिए, लेकिन जानकारी खो दी है x एक Bar#X है। यह ठीक काम करता है अगर मैं प्रकार व्याख्या:

baz[Bar](x) 

वहाँ स्काला baz के लिए सही प्रकार पैरामीटर अनुमान कर बनाने के लिए एक तरीका है?
यदि नहीं, तो सामान्य उत्तर क्या है जो इसे असंभव बनाता है?

+2

कोई जवाब नहीं है, लेकिन यह ध्यान देने योग्य है कि यदि आप एक प्रकार प्रक्षेपण के बजाय किसी प्रकार के डिज़ाइनर का उपयोग करके 'x' टाइप करते हैं, तो यह कार्य करता है- उदा। 'वस्तु बार बार बार फैली हुई है; वैल एक्स: बीएआरएक्स = "ए"; baz (एक्स) '। –

+3

ध्यान देने योग्य भी है: आप संकलक को यह समझ सकते हैं कि आप वास्तव में _do' को 'bar # X' जैसे अविश्वसनीय रूप से बदसूरत' val x: bX forome {val b: bar} = " एक ": बीएक्स के लिए कुछ {वैल बी: बार}'। –

+0

अजीब उपयोग के मामले की तरह लगता है। तुम ऐसा क्यों करना चाहते हो? –

उत्तर

2

कार्यक्रम संदर्भ में इस अंतर्निहित रूपांतरण जोड़कर संकलित:

implicit def f(x: Bar#X): Foo#X = x 

के रूप में यह अंतर्निहित रूपांतरण किसी भी F <: Foo के लिए सही है, तो मुझे आश्चर्य है कि क्यों संकलक नहीं करता है अपने आप में है।

1

तुम भी कर सकते हैं:

trait Foo { 
    type X 
} 
trait Bar extends Foo { 
    type X = String 
} 
class BarImpl extends Bar{ 
    def getX:X="hi" 
} 
def baz[F <: Foo, T <: F#X](clz:F, x: T): Unit = { println("baz worked!")} 
val bi = new BarImpl 
val x: Bar#X = bi.getX 
baz(bi,x) 

लेकिन:

test.scala:22: error: inferred type arguments [Nothing,java.lang.String] do not conform to method baz2's type parameter bounds [F <: this.Foo,T <: F#X] 
baz2(x) 
^ 
one error found 

मैं मूल रूप से लगता है, एफ <: फू संकलक कि एफ हो गया है बताता है

def baz2[F <: Foo, T <: F#X](x: T): Unit = { println("baz2 failed!")} 
baz2(x) 

के साथ विफल फू का एक उप प्रकार, लेकिन जब यह एक्स प्राप्त करता है तो यह नहीं जानता कि आपकी विशेष एक्स से आता है। आपका एक्स सिर्फ एक स्ट्रिंग है, और बार को वापस इंगित करने वाली जानकारी को बनाए रखता नहीं है।

ध्यान दें कि:

def baz3[F<: Foo](x : F#X) = {println("baz3 worked!")} 
baz3[Bar]("hi") 

भी काम करता है। तथ्य यह है कि आपने एक वैल एक्स परिभाषित किया है: बार # एक्स = ??? बस इसका मतलब है ??? जो भी बार # एक्स संकलित समय पर हो सकता है, तक सीमित है ... संकलक जानता है कि बार # एक्स स्ट्रिंग है, इसलिए एक्स का प्रकार सिर्फ स्ट्रिंग से किसी स्ट्रिंग से भिन्न नहीं है।

+0

हां, कंपाइलर केवल 'स्ट्रिंग' को देखता है और 'स्ट्रिंग' के बजाय 'बार # एक्स' के साथ टाइप को एनोटेट करने के बावजूद' Foo' संदर्भ खो देता है। मेरा एकमात्र समाधान अब तक 'फू' पर अमूर्त है और अंत में 'बार' प्रदान करता है। लेकिन यह वास्तव में मेरे लिए एक समस्या है क्योंकि यह प्रतिबंधित करता है कि मैं 'बाज़' क्या कर सकता हूं ... (मेरे मामले में, 'बाज' भी एक निहित है) – betehess

+0

दाएं। आप इस तरह से सोच सकते हैं: टाइप एक्स फू का सदस्य है, जैसे जावा में अन्य स्थिर बनाम सदस्य चर के साथ। उदाहरण के बिना इसे एक्सेस करने का प्रयास करना किसी उदाहरण के बिना सदस्य चर का उपयोग करने की कोशिश करना है। – Brian

+0

इन: 'विशेषता हैट टाइप {टाइप एक्स} कक्षा फू (वैल टी: हैसटाइप) {टाइप ए = टी.एक्स}'। आपके पास अलग-अलग 'ए' के ​​साथ कई 'फू' हो सकते हैं, प्रत्येक विशेष पारित 'टी' ('हैट टाइप' का उदाहरण) पर निर्भर करता है। प्रकार गतिशील है और इसलिए किसी भी तरह से निर्दिष्ट किया जाना है। उदाहरण के लिए Foo # ए आपको व्यक्ति या व्यक्ति के मुकाबले 'ए' के बारे में और अधिक नहीं बताता है। यह आपको किसी व्यक्ति की आयु के बारे में बताएगा। एक उदाहरण 't' प्रकार की जानकारी प्रदान करता है। – Brian