2013-07-20 1 views
9

में उच्च प्रकार के प्रकारों के प्रकार अनुरूपता का परीक्षण कैसे करें मैं परीक्षण करने की कोशिश कर रहा हूं कि दो "कंटेनर" एक ही उच्च प्रकार के प्रकार का उपयोग करते हैं या नहीं। निम्नलिखित कोड को देखो:स्कैला

import scala.reflect.runtime.universe._ 

class Funct[A[_],B] 

class Foo[A : TypeTag](x: A) { 
    def test[B[_]](implicit wt: WeakTypeTag[B[_]]) = 
    println(typeOf[A] <:< weakTypeOf[Funct[B,_]]) 

    def print[B[_]](implicit wt: WeakTypeTag[B[_]]) = { 
    println(typeOf[A]) 
    println(weakTypeOf[B[_]]) 
    } 
} 

val x = new Foo(new Funct[Option,Int]) 

x.test[Option] 
x.print[Option] 

उत्पादन होता है:

false 
Test.Funct[Option,Int] 
scala.Option[_] 

हालांकि, मैं अनुरूपता परीक्षण सफल होने की उम्मीद है। मैं क्या गलत कर रहा हूं? मैं उच्च प्रकार के प्रकार के लिए कैसे परीक्षण कर सकता हूं?

स्पष्टीकरण

मेरे मामले में, मान मैं परीक्षण कर रहा हूँ (उदाहरण में x: A) एक मैक्रो में एक List[c.Expr[Any]] में आते हैं। तो स्थिर समाधान (जैसा कि मैंने दिया है) पर निर्भर कोई समाधान, मेरी समस्या का समाधान नहीं करेगा।

+1

अपनी अपेक्षाओं को थोड़ा सा वापस करने के लिए: 'निहित [कार्य [विकल्प, int] <: pedrofurla

+0

https: //gist.github से।कॉम/xeno-by/6054650 मैं देख सकता हूं कि टाइप रीइफायर को बी के लिए एक प्रकार का टैग नहीं दिखता है, इसलिए आपको कमजोर टाइप प्रकार [Funct [B, _]] से सही प्रकार नहीं मिलता है। –

+0

ठीक है, अब मैं देखता हूं कि समस्या क्या है। यह फिर से पैरामीटर परिभाषाओं और अन्यत्र उपयोग में अंडरस्कोर के बीच मिश्रण है। 'टाइपटाग [बी [_]]' में अंडरस्कोर का अर्थ अस्तित्व का प्रकार है, इसलिए आपको 'बी' के लिए एक प्रकार का टैग नहीं मिलता है, लेकिन इसके ऊपर मौजूद अस्तित्व वाले रैपर के लिए। नतीजतन 'typeOf [Funct [B, _]]' इस प्रकार के टैग का उपयोग नहीं कर सकता है और परेशान हो जाता है। –

उत्तर

8

यह अंडरस्कोर के बीच mixup है प्रकार पैरामीटर परिभाषाओं और अन्य जगहों में प्रयोग किया जाता है। TypeTag[B[_]] में अंडरस्कोर का अर्थ अस्तित्व का प्रकार है, इसलिए आपको B के लिए टैग नहीं मिलता है, लेकिन इसके ऊपर एक अस्तित्वत्मक रैपर के लिए, जो मैन्युअल पोस्टप्रोसेसिंग के बिना काफी बेकार है।

परिणामस्वरूप typeOf[Funct[B, _]] जो कच्चे B के लिए टैग की आवश्यकता है, रैपर के लिए टैग का उपयोग नहीं कर सकता है और परेशान हो जाता है। परेशान होने से मेरा मतलब है कि यह टैग को दायरे में विभाजित करने से इंकार कर देता है और संकलन त्रुटि के साथ विफल रहता है। यदि आप इसके बजाय weakTypeOf का उपयोग करते हैं, तो वह सफल होगा, लेकिन यह सब कुछ के लिए स्टब्स उत्पन्न करेगा जो इसे विभाजित नहीं कर सकता है, परिणाम को सबटाइपिंग चेक के लिए बेकार बना देता है।

ऐसा लगता है कि इस मामले में हम वास्तव में अर्थ में स्काला के सीमाओं को पार कर कोई रास्ता नहीं है कि वहाँ हमें WeakTypeTag[B] में कच्चे B का उल्लेख करने के लिए, क्योंकि हम स्काला में तरह बहुरूपता जरूरत नहीं है। उम्मीद है कि DOT जैसे कुछ हमें इस असुविधा से बचाएंगे, लेकिन इस बीच आप इस कामकाज का उपयोग कर सकते हैं (यह सुंदर नहीं है, लेकिन मैं एक सरल दृष्टिकोण के साथ आने में सक्षम नहीं हूं)।

import scala.reflect.runtime.universe._ 

object Test extends App { 
    class Foo[B[_], T] 
    // NOTE: ideally we'd be able to write this, but since it's not valid Scala 
    // we have to work around by using an existential type 
    // def test[B[_]](implicit tt: WeakTypeTag[B]) = weakTypeOf[Foo[B, _]] 
    def test[B[_]](implicit tt: WeakTypeTag[B[_]]) = { 
    val ExistentialType(_, TypeRef(pre, sym, _)) = tt.tpe 

    // attempt #1: just compose the type manually 
    // but what do we put there instead of question marks?! 
    // appliedType(typeOf[Foo], List(TypeRef(pre, sym, Nil), ???)) 

    // attempt #2: reify a template and then manually replace the stubs 
    val template = typeOf[Foo[Hack, _]] 
    val result = template.substituteSymbols(List(typeOf[Hack[_]].typeSymbol), List(sym)) 
    println(result) 
    } 
    test[Option] 
} 

// has to be top-level, otherwise the substituion magic won't work 
class Hack[T] 

एक चतुर पाठक देखेंगे कि मैं foo के हस्ताक्षर में WeakTypeTag इस्तेमाल किया है, भले ही मैं TypeTag उपयोग करने के लिए सक्षम होना चाहिए। आखिरकार, हम Option पर foo को कॉल करते हैं जो एक अच्छी तरह से व्यवहार किया गया प्रकार है, इस अर्थ में कि इसमें अनसुलझे प्रकार पैरामीटर या स्थानीय कक्षाएं शामिल नहीं हैं जो TypeTag एस के लिए समस्याएं उत्पन्न करती हैं। दुर्भाग्यवश, https://issues.scala-lang.org/browse/SI-7686 की वजह से यह इतना आसान नहीं है, इसलिए हमें कमजोर टैग का उपयोग करने के लिए मजबूर होना पड़ता है, भले ही हमें इसकी आवश्यकता नहीं होनी चाहिए।

+0

क्या फू पर एक सार हो सकता है? – Edmondo1984

5

निम्नलिखित एक ऐसा उत्तर है जो मैंने जो उदाहरण दिया है (और दूसरों की मदद कर सकता है) के लिए काम करता है, लेकिन मेरे (गैर-सरलीकृत) मामले पर लागू नहीं होता है।

@ pedrofurla के संकेत से चोरी, और का उपयोग कर टाइप कक्षाएं:

trait ConfTest[A,B] { 
    def conform: Boolean 
} 

trait LowPrioConfTest { 
    implicit def ctF[A,B] = new ConfTest[A,B] { val conform = false } 
} 

object ConfTest extends LowPrioConfTest { 
    implicit def ctT[A,B](implicit ev: A <:< B) = 
    new ConfTest[A,B] { val conform = true } 
} 

और Foo से जोड़ें:

def imp[B[_]](implicit ct: ConfTest[A,Funct[B,_]]) = 
    println(ct.conform) 
अब

:

x.imp[Option] // --> true 
x.imp[List] // --> false