2013-08-19 8 views
6

this question की पंक्तियों के साथ की सबसे बड़ी आम उप-प्रकार का पता लगाएं, मैं दो प्रकार के सबसे बड़ा आम उप प्रकार अनुमान लगाने के लिए ए और बीदो स्काला प्रकार

"एक तरह स्काला संकलक पाने के लिए एक रास्ता खोजने के लिए कोशिश कर रहा हूँ बी ", जहां परिभाषा है बिना:

(A without B = C) === (A = C with B) 

या एक प्रकार समारोह है कि सी, रिटर्न जहां:

संपादित करें:

A <: C && C <:!< B 

यानी। ए सी और सी का उप प्रकार बी

वास्तव में मुझे उम्मीद है कि यह "सबसे बड़ा आम उप प्रकार" जैसा नहीं होगा, क्योंकि मुझे वास्तव में A <: B की आवश्यकता नहीं है।

उपयोग:

trait Syntax 

trait ANYSYNTAX extends Syntax 
trait NUMERIC extends ANYSYNTAX 
trait DISCRETE extends ANYSYNTAX 
trait POSITIVE extends ANYSYNTAX 
trait CONST extends ANYSYNTAX  
type NUMCONST = NUMERIC with CONST 
type POSCONST = POSITIVE with CONST 
type ORDINALCONST = DISCRETE with CONST 
type INTEGER = NUMERIC with DISCRETE 
type POSNUM = POSITIVE with NUMERIC 
type POSINT = POSNUM with INTEGER 
type INTCONST = INTEGER with NUMCONST with ORDINALCONST 
type POSNUMCONST = POSNUM with POSCONST with NUMCONST 
type POSINTCONST = POSNUMCONST with INTCONST with POSINT 

तब मैं, इस प्रकार प्रकार की कमी का प्रचार करने में सक्षम होना चाहते हैं:

abstract class Expression[+R](val args: Expression[_]*) 

case class Add[A <: R, R <: NUMERIC](arg1: Expression[A], arg2: Expression[A]) extends Expression[R] { 
case class Subtract[A <: R, R : A without POSITIVE](arg1: Expression[A], arg2: Expression[A]) extends Expression[R] { 
case class Multiply[A <: R, R <: NUMERIC](arg1: Expression[A], arg2: Expression[A]) extends Expression[R]{ 
case class Divide[A <: R, R : A without DISCRETE](arg1: Expression[A], arg2: Expression[A]) extends Expression[R] { 

मैं उधार कुछ प्रकार की कमी का उपयोग कर कुछ के साथ आने की कोशिश कर रहा है अन्य एसओ उत्तरों से:

sealed class =!=[A,B] 

trait LowerPriorityImplicits { 
    implicit def equal[A]: =!=[A, A] = sys.error("should not be called") 
} 
object =!= extends LowerPriorityImplicits { 
    implicit def nequal[A,B](implicit same: A =:= B = null): =!=[A,B] = 
    if (same != null) sys.error("should not be called explicitly with same type") 
    else new =!=[A,B] 
} 

// Encoding for "A is not a subtype of B" 
trait <:!<[A, B] 

// Uses ambiguity to rule out the cases we're trying to exclude 
implicit def nsub[A, B] : A <:!< B = null 
implicit def nsubAmbig1[A, B >: A] : A <:!< B = null 
implicit def nsubAmbig2[A, B >: A] : A <:!< B = null 

मेरे पास कुछ परीक्षण मामले हैं:

implicitly[POSINT <:!< CONST] 
implicitly[POSITIVE <:!< OPINION] 
implicitly[DOGMA <:!< CONST] 

implicitly[POSINTCONST <:< POSITIVE with CONST] 
implicitly[POSINTCONST <:< POSCONST] 
implicitly[POSITIVE with CONST <:!< POSINTCONST] 

implicitly[POSITIVE =:= POSCONST without CONST] 
implicitly[NUMERIC =:= INTEGER without DISCRETE] 
implicitly[POSINT =:= POSINTCONST without CONST] 

ये असफल चाहिए:

implicitly[POSINT =:= POSINTCONST without OPINION] 
implicitly[POSINT with OPINION =!= POSINTCONST without OPINION] 
+0

मुझे यकीन नहीं है कि मैं आपकी परिभाषा को समझता हूं। ऐसा लगता है कि 'ए <: बी', फिर' सी' मौजूद नहीं है, और अन्यथा 'सी' केवल 'ए' है। –

+0

@TravisBrown उदाहरण के लिए, 'सी: पॉजिंट', 'बी: कॉन्स्ट'। फिर 'ए: सी बी के साथ = POSINTCONST। मेरी पहली परिभाषा के अनुसार, 'POSINTCONST बिना CONST =: = POSINT'। यदि दूसरी ओर 'ए <:! <बी', उदाहरण के लिए। 'NUMCONST बिना सकारात्मक 'तो मैं कहूंगा कि' सी: NUMCONST' जैसा कि आप कहते हैं। – RealName

+0

असल में @ ट्रेविस मैंने अपनी दूसरी परिभाषा में एक त्रुटि की है (अब मुझे उम्मीद है)। – RealName

उत्तर

1

खैर बेतरतीब ढंग से कुंजीपटल एक बहुत कोसने और जितना मैं प्रकार की कमी के बारे में समझ सकते हैं के रूप में पढ़ने के बाद, यह क्या मैं के साथ आए हैं है: यह है कि यह काम करने के लिए लगता है

// A without B is C 
sealed abstract class isWithout[A, B, C] 

object Syntax { 

    implicit def composedWithout[A <: C, B, C](implicit ev: C <:!< B): isWithout[A, B, C] = new isWithout[A, B, C] { 
    def apply(a: A) = a 
    } 

    type without[A, B] = { 
    type l[C] = isWithout[A, B, C] 
    } 
} 

टेस्ट:

implicitly[isWithout[POSCONST, POSITIVE, CONST]] 
implicitly[isWithout[POSINTCONST, DISCRETE, POSNUMCONST]] 
implicitly[isWithout[POSINTCONST, DISCRETE, POSITIVE]] 
implicitly[isWithout[POSNUM, CONST, POSNUM]] 
implicitly[isWithout[POSCONST, CONST, POSITIVE ]] 
implicitly[isWithout[POSCONST, POSITIVE, CONST ]] 
implicitly[isWithout[INTEGER, DISCRETE, NUMERIC ]] 
implicitly[isWithout[POSINTCONST, CONST, POSINT ]] 

और विफल रहता है जब यह होना चाहिए:

implicitly[isWithout[POSINTCONST, INTCONST, POSINTCONST]] 
implicitly[isWithout[NUMERIC, ANYSYNTAX, ANYSYNTAX]] 
implicitly[isWithout[INTEGER, POSITIVE, POSINT]] 
implicitly[isWithout[POSNUM, DISCRETE, POSCONST]] 

implicitly संकलक टी हो जाता है o वर्तमान अंतर्निहित दायरे में एक निहित कार्य की तलाश करें जो आवश्यक प्रकार की वस्तु उत्पन्न कर सकती है (इस मामले में, कक्षा का एक उदाहरण है बिना)। यदि यह उस व्यक्ति को मिलता है जो प्रकार हस्ताक्षर को संतुष्ट करता है तो यह संकलित करता है (मुझे नहीं लगता कि यह वर्ग रिटर्न में परिभाषित apply विधि है)। महत्वपूर्ण बिंदु प्रकार हस्ताक्षर है, जो प्रश्न में उल्लिखित <:!< का उपयोग करता है और माइल्स द्वारा किसी अन्य SO उत्तर से उधार लिया जाता है।

इस प्रकार का हस्ताक्षर कहते हैं: एक सी के एक उप-प्रकार और सी बी की एक उप-प्रकार एक वैकल्पिक संस्करण (प्रश्न के पहले परिभाषा के अनुरूप) नहीं होना चाहिए होगा:

implicit def composedWithout[A <: C with B, B, C](implicit ev: C <:!< B): isWithout[A, B, C] = new isWithout[A, B, C] { 
    def apply(a: A, b: B) = a 
} 

यह कर सकते हैं कुछ तरीकों से इस्तेमाल किया जा:

  1. रूप implicitly के ऊपर उपयोग के साथ दिखाया गया है प्रकार पदानुक्रम (। यानी परीक्षण मामलों) की वैधता की जांच करने के लिए,।

  2. एक विधि पैरामीटर के प्रकार निर्दिष्ट करने के लिए:

    def test[R : without[POSINTCONST, DISCRETE]#l](v: R) = v

    ध्यान दें कि इस प्रकार के प्रक्षेपण का उपयोग करता without#l[C] = isWithout[A, B, C] एक संदर्भ के रूप में बाध्य जो करने के लिए संकलक desugars:

    def test[R](v: R)(implicit $ev0: isWithout[POSINTCONST, DISCRETE, R]) = v 
    

    इस प्रकार यह निर्दिष्ट निहितार्थ को दायरे में होना आवश्यक है।

  3. एक प्रकार बाधा के रूप में, के रूप में मूल प्रश्न में अनुरोध:

    case class Subtract[A <: R, R <: A without POSITIVE](arg1: Expression[A], arg2: Expression[A]) extends BinaryPrimitive[A, R](arg1, arg2)

    यह संकलित हालांकि मैं मानता मैंने अभी तक कुछ नहीं चला है तो यह कर नहीं किया जा सकता है कि मैं क्या लगता है कि यह कर रहा है ।

3

ध्वनि आप एक कम से कम अपर बाउंड स्केला प्रकार के (एलयूबी) चाहते हैं की तरह? मैं प्रेरणा के लिए माइल्स 'बेकार पुस्तकालय की ओर देखता हूं जहां वास्तव में LUBConstraint है।

या यदि आप ग्रेटर लोअर बाउंड (जीएलबी) चाहते हैं तो मुझे डर है कि मुझे आपको एक मैक्रो परिभाषा का उपयोग करने के लिए संदर्भित करना होगा जिसमें आप एलयूबी या जीएलबी प्राप्त कर सकते हैं, Types देखें।

+1

लाइट्स और ग्लब्स को रनटाइम रिफ्लेक्शन के साथ भी गणना की जा सकती है। –

+0

@wheaties मैंने बेकार देखा है और इसे 'देखा' है, लेकिन मुझे यह बहुत अभेद्य लगता है। मेरा मानना ​​है कि जीएलबी वह है जो मैं चाहता हूं और वह लिंक उपयोगी हो सकता है, हालांकि मैं एक और विस्तृत उत्तर की उम्मीद कर रहा था। – RealName

+0

@ यूजीन रनटाइम प्रतिबिंब अच्छा होगा, आखिरकार, मैं रन-टाइम पर नए अभिव्यक्तियों को बनाने में सक्षम होना चाहता हूं। – RealName

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