2016-02-27 12 views
8

मुझे एक अंतर्दृष्टि के बारे में एक अजीब कंपाइलर त्रुटि मिली जो वास्तव में मौजूद है लेकिन किसी कारण से नहीं मिल सका। इसलिए मैंने एक छोटा परीक्षण केस बनाया है जो रहस्यमय व्यवहार को पुन: उत्पन्न करता है।कुछ मामलों में उच्च आदेश प्रत्यारोपण क्यों अनदेखा किया जाता है?

trait Hide { 
    type T 
} 
object HideString extends Hide { 
    override type T = String 
} 
object HideBool extends Hide { 
    override type T = Boolean 
} 

सरल प्रकार के लिए असीमित लक्ष्य के रूप में उपयोग किया जाने वाला सरल प्रकार।

def id[H <: Hide, C](x : C)(implicit ev : C => H#T) : H#T = ev(x) 
def drop[H <: Hide, C](x : C)(implicit ev : C => H#T) : Int = { 
    println(ev(x)) 
    1 
} 
def idSeq[H <: Hide, C](x : Seq[C])(implicit ev : Seq[C] => Seq[H#T]) : Seq[H#T] = ev(x) 
def dropSeq[H <: Hide, C](x : Seq[C])(implicit ev : Seq[C] => Seq[H#T]) : Int = { 
    println(ev(x)) 
    1 
} 

विधियां जो लागू रूपांतरणों पर भरोसा करती हैं। यह मूल रूप से 2x2 मैट्रिक्स है। id विधियां परिवर्तित प्रकार लौटाती हैं और drop विधियां आंतरिक रूप से रूपांतरण का उपयोग करती हैं और कुछ स्थिर लौटती हैं। सामान्य तरीके सटीक रूप से परिवर्तित प्रकार पर चलती हैं और Seq विधियां अनुक्रमों पर चलती हैं।

implicit def exString(x : String) : HideString.type#T = x 
implicit def highString[F[_]](x : F[String]) : F[HideString.type#T] = x 

अंतर्निहित रूपांतरण highString से ऊपर उच्च क्रम प्रकार के साथ परिभाषित किया गया है।

ImplicitResolution.scala:98: error: No implicit view available from Seq[String] => Seq[test.implicits.HighReduction.Hide#T]. 
    val r2 = dropSeq(Seq("i", "IO")) 

निम्नलिखित मैट्रिक्स में संक्षेप किया जा सकता है कि:

|  | id | drop | 
|--------+------+------| 
| normal | pass | pass | 
| seq | pass | fail | 

मैं ठीक dropSeq विधि के लिए अंतर्निहित रूपांतरण परिभाषित उपयोग करते हैं तो

val s1 = id("sdf") 
val s2 = drop("aero") 

val r1 = idSeq(Seq("a", "bc")) 
val r2 = dropSeq(Seq("i", "IO")) 

वास्तव में रूपांतरण का उपयोग करने की कोशिश कर मुझे एक त्रुटि लाता है यह सामान्य रूप से पाया जाता है:

implicit def seqBool(x : Seq[Boolean]) : Seq[HideBool.type#T] = x 

val a1 = idSeq(Seq(true, false)) 
val a2 = dropSeq(Seq(false, true)) 

और इसके अलावा अगर मैं स्पष्ट रूप से निहित तर्क dropSeq निर्दिष्ट काम करना शुरू किया:

val r2i = dropSeq(Seq("i", "IO"))(highString[Seq] _) 

और वह अजीब बात है। highString निहित सभी आवश्यकताओं के अनुरूप है। और इसे implicit के रूप में घोषित किया गया है, इसलिए इसे कंपाइलर द्वारा पाया जाना चाहिए। और idSeq के मामले में यह वास्तव में पाया जाता है। तो, dropSeq मामले में इसे क्यों नजरअंदाज किया जाता है?

उत्तर

1

आपके मामले में idSeq और dropSeq के बीच एकमात्र अंतर रिटर्न प्रकार है: आपने स्कैला कंपाइलर में कुछ कोने केस मारा है जो स्कैला समुदाय को संकेत देने योग्य है।

जिसके अनुसार, अपने idSeq गलत हस्ताक्षर है: H#X निर्दिष्ट H प्रकार के लिए एक्स प्रकार मतलब यह नहीं है, बल्कि यह है कि संकलक द्वारा हल किया गया है एच (नहीं एक के किसी भी उदाहरण के लिए X, देख डैनियल Sobral स्पष्टीकरण यहाँ What does the `#` operator mean in Scala?)

क्या आप शायद क्या करना चाहते हैं एच और अपने परिणाम प्रकार है, जो आसान है अगर आप एक अधिक पठनीय हस्ताक्षर प्राप्त करने के लिए प्रकार उपनाम परिचय के बीच एक रिश्ता स्थापित करना है:

object Hide { 
    type HideAux[X] = Hide { type T = X} 
} 

आप कर सकते हैं फिर वें जैसे कोड को फिर से लिखें है:

def idSeq[B,H <: HideAux[B], C](x : Seq[C])(implicit ev : Seq[C] => Seq[B]) : Seq[B] = ev(x) 
    def dropSeq[B,H <: HideAux[B], C](x : Seq[C])(implicit ev : Seq[C] => Seq[B]) : Int = { 
    println(ev(x)) 
    1 
    } 

इस कोड संकलन, और यह भी सूचना है कि अगर आप सही तरीके सामान्य और typeclasses उपयोग करते हैं, तो आपके पास दो अलग अलग तरीकों id और idSeq की जरूरत नहीं होगी क्योंकि गतिशील व्यवहार typeclass से ही उपलब्ध कराया जा रहा है।

+2

यदि आप वर्णन करते हैं कि "स्कैला कंपाइलर में कोने केस" के लिए कोई समस्या दायर की गई है तो मैं आपको बक्षीस देने के इच्छुक हूं। मुझे लगता है कि यह कुछ कोने का मामला था, लेकिन आपने अभी भी यह जानने के लिए पर्याप्त जानकारी प्रदान नहीं की है कि यह * अपेक्षित * व्यवहार है, या यदि यह वास्तव में कंपाइलर में एक बग है। यह भी अच्छा होगा अगर आप उस लटकने से छुटकारा पाएं '} ' – DaoWen

+0

आपके दो कार्यों में वापसी प्रकार को छोड़कर एक ही हस्ताक्षर है, लेकिन आप आर 1 और आर 2 के लिए प्रकार अनुमान का उपयोग करते हैं (इसलिए रिटर्न प्रकार का उपयोग अंतर्निहित रिज़ॉल्यूशन के लिए नहीं किया जा सकता है)। यदि उपलब्ध प्रकार की जानकारी के साथ आर 1 के लिए निहितार्थ को हल करना संभव है, तो आर 2 के लिए निहितार्थ को हल करना संभव है: दिया गया है कि ड्रॉप कार्य और ड्रॉपसेक नहीं करता है, यह संभावना है कि समस्या जेनेरिक प्रकार और प्रकार अनुमानों के साथ है। – Edmondo1984

+0

'-Xlog-implicits' का उपयोग करके कुछ रोचक त्रुटियां उत्पन्न होती हैं। –

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