2017-08-11 14 views
15

मैंने =:= का उपयोग उदाहरण के रूप में सरल न्यूनतम उदाहरण बनाने के उद्देश्य से लैम्ब्डा टाइप किया।टाइप लैम्ब्डा को सही तरीके से परिभाषित करने के लिए कैसे करें?

=:= प्रकार दो तर्क लेते हैं, मैं एक प्रकार के स्तर पर करी करना चाहता हूं।

मैं अनुभवहीन कार्यान्वयन type Curry[G] = {type l[L] = L =:= G} ले लेकिन व्यावहारिक में यह त्रुटियों का कारण बनता उपयोग करता है:

type X = Int 
type Y = Int 

type CurryInt[T] = T =:= Int 
type Curry[G] = {type l[L] = L =:= G} 
type CurrStatic = {type l[L] = L =:= Int} 
object CurryObj {type l[L] = L =:= Int} 

trait Apply[P[_], T] 
implicit def liftApply[P[_], T](implicit ev : P[T]) = new Apply[P,T] {} 

implicitly[Apply[CurryInt, Y]] // ok 
implicitly[Apply[Curry[X]#l, Y]] // fails 
implicitly[Apply[Curry[X]#l, Y]](liftApply) // fails 
implicitly[Apply[Curry[X]#l, Y]](liftApply[Curry[X]#l, Y]) // ok 
implicitly[Apply[CurrStatic#l, Y]] // fails 
implicitly[Apply[CurryObj.l, Y]] // ok 

प्रकार निष्कर्ष यहाँ टूट जाता है। इसे काम करने के लिए मुझे लैम्बडास को कैसे परिभाषित करना चाहिए?

उत्तर

2

थोड़ा अधिक वर्बोज़, लेकिन संकलित :) (स्केला 2.12.3)

type X = Int 
    type Y = Int 

    type CurryInt[T] = T =:= Int 
    type Curry[G] = {type l[L] = =:=[L, G]} 
    type CurrStatic = {type l[L] = L =:= Int} 
    object CurryObj {type l[L] = L =:= Int} 

    trait Apply[P[_], T] 
    implicit def liftApply[P[_], T](implicit ev : P[T]) = new Apply[P,T] {} 


    type L1[R] = =:=[R, X] 
    type L2[R] = =:=[R, Int] 
    implicitly[Apply[CurryInt, Y]] // ok 
    implicitly[Apply[L1, Y]] // ok 
    implicitly[Apply[L1, Y]](liftApply[L1, Y]) // ok 
    implicitly[Apply[Curry[X]#l, Y]](liftApply[Curry[X]#l, Y]) // ok 
    implicitly[Apply[L2, Y]] // ok 
    implicitly[Apply[CurryObj.l, Y]] // ok 
+0

जल्द ही: प्रकार प्रक्षेपण का उपयोग नहीं करता है।टाइप घोषणा को अनबाउंड वैरिएबल रखने की अनुमति है – ayvango

+0

आप अपनी आवश्यकताओं के अनुसार विशिष्ट नहीं थे, हालांकि यह समाधान संकलित करता है कि आप 'प्रक्षेपण प्रक्षेपण' के साथ क्यों जाने का प्रयास कर रहे हैं? क्या यह सिर्फ एक अभ्यास है? – pedromss

+0

मैं अनजान था कि टाइप अभिव्यक्ति में अनबाउंड प्रकारों की अनुमति है। तो मैंने टाइप स्तर में 'λx.λy.x == y' जैसे कुछ एन्कोड करने का प्रयास किया। मैं कल्पना नहीं कर सका कि सरल 'λx.x == y' सही स्केल अभिव्यक्ति होगी। – ayvango

3

अपने उदाहरण के इस सरलीकृत संस्करण पर विचार करें:

trait Secret 
type Curry = { type l[L] = Secret } 

def foo[P[_], T](ev : P[T]) = ??? 
val bar: Curry#l[Int] = ??? 

foo(bar) 

जब foo बुला मूल्य bar बस है Secret टाइप करें, संकलक यह नहीं जानता कि आपका विशेष Secret कहां से आता है।

आपका bar मान केवल Secret है, और यह Curry#l[Int] पर इंगित करने वाली जानकारी को बनाए रखता नहीं है।

कंपाइलर P => Curry#l और T => Int का अनुमान नहीं लगा सकता है।

संकलक केवल Secret देखता है और Curry#l[Int] बजाय Secret साथ प्रकार व्याख्या के बावजूद Curry#l संदर्भ खो देता है।

एक अन्य उदाहरण (this सवाल से आ रही है), एक समान व्यवहार को उजागर:

trait Curry { type l } 
trait CurryB extends Curry { type l = String } 

def foo[P <: Curry](x: P#l) = ??? 
val bar: CurryB#l = ??? 

foo(bar) 

CurryObj स्थिति अलग है, विचार है कि CurryInt#l, Curry#l, और CurrStatic#l सिर्फ उपनाम टाइप कर रहे हैं। CurryObj.l, इसके बजाय, ठोस वस्तु CurryObj का वास्तविक प्रकार है।

के इस (आरईपीएल) को एक नजर है:

scala> trait Secret 
defined trait Secret 

scala> type Curry = { type l[L] = Secret } 
defined type alias Curry 

scala> object CurryObj { type l[L] = Secret } 
defined object CurryObj 

scala> object S extends Secret 
defined object S 

scala> val foo0: Curry#l[Int] = S 
foo0: Secret = [email protected] 

scala> val foo1: CurryObj.l[Int] = S 
foo1: CurryObj.l[Int] = [email protected] 

ध्यान दें कि प्रकार उर्फ ​​Curry#l[Int] ->Secret तुरंत, बजाय वास्तविक प्रकार CurryObj.l[Int] रखा जाता है हल हो गई है।

+0

टाइप 'करी' मेरे उदाहरण से 'CurrStatic' की तरह है। यह 'करीओबज' के समान दिखता है। एक मामले में प्रकार की जानकारी क्यों सहेजी जाती है और दूसरे में खो जाती है? – ayvango

+0

मैंने आपकी चिंता का समाधान करने के लिए उत्तर अपडेट किया है। –

+0

इसका अर्थ है। लेकिन मेरे मामले में 'करी' एल' का उपयोग 'Int' लागू किए बिना किया जाता है। और 'गुप्त' में टाइप पैरामीटर भी है, इसलिए इसे समाप्त नहीं किया जा सका। जैसा कि मैंने '-इंटर-डीबग' में देखा था, टाइप पैरामीटर संरक्षित है लेकिन असामान्य रूप में – ayvango

0

ऐसा लगता है कि स्कैला कंपाइलर प्रकार के अनुमानों से नग्न प्रकारों को संभाल नहीं सकता था। मैंने -Ytyper-debug आउटपुट का पता लगाया और पाया कि सभी आवश्यक प्रकार की जानकारी दूर की जाती है लेकिन किसी स्पष्ट कारण के लिए इसे अस्वीकार कर दिया जाता है। लेकिन यह अभी भी एक विशेषता के अंदर प्रकार lambdas wrapping अभिव्यक्ति प्राप्त करना संभव है। That answer ने मुझे समाधान की दिशा में अंतर्दृष्टि दी।

type X = Int 
type Y = Int 

trait Wrap { 
    type l[T] 
} 
trait GenWrap[W[_]] extends Wrap { 
    final type l[T] = W[T] 
} 

type CInt[T] = T =:= Int 
class CurryInt extends Wrap {type l[T] = T =:= Int} 
class Curry[U] extends Wrap {type l[T] = T =:= U} 
type TCurry[U] = Wrap {type l[T] = T =:= U} 

trait Apply[W <: Wrap, T] 
implicit def lift[W <: Wrap, T](implicit ev : W#l[T]) = new Apply[W,T] {} 

implicitly[Apply[CurryInt, Y]] 
implicitly[Apply[Curry[X], Y]] 
implicitly[Apply[TCurry[X], Y]] 
implicitly[Apply[GenWrap[CInt], Y]] 
संबंधित मुद्दे

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