2009-05-18 10 views
28

मान लीजिए मैं निम्नलिखित वर्ग है:उच्च kinded जेनरिक

public class FixExpr { 
    Expr<FixExpr> in; 
} 

अब मैं एक सामान्य तर्क पेश करने, Expr के उपयोग पर सार संक्षेप हैं:

public class Fix<F> { 
    F<Fix<F>> in; 
} 

लेकिन ग्रहण नहीं करता है ' टी इस तरह:

प्रकार एफ सामान्य नहीं है; इसे ठीक < < एफ > >

तर्क के साथ parametrized नहीं किया जा सकता यह सब पर संभव है या मैं कुछ का कारण बनता है कि विशेष रूप से यह तोड़ने के लिए अनदेखा कर दिया?

कुछ पृष्ठभूमि जानकारी: हास्केल में यह सामान्य कार्यों को लिखने का एक आम तरीका है; मैं जावा को पोर्ट करने की कोशिश कर रहा हूं। ऊपर दिए गए उदाहरण में टाइप तर्क एफ में सामान्य प्रकार की बजाय * -> * है। हास्केल में यह इस तरह दिखता है:

newtype Fix f = In { out :: f (Fix f) } 
+1

वास्तविक समस्या आप इस के साथ हल करने की कोशिश कर रहे हैं क्या है? क्या इसे टेम्पलेट का उपयोग करके आसानी से हल नहीं किया जा सकता है? – KitsuneYMG

उत्तर

23

मुझे लगता है कि तुम क्या करने की कोशिश कर रहे हैं बस नहीं है जावा जेनरिक द्वारा समर्थित।

public class Foo<T> { 
    public T<String> bar() { return null; } 
} 

का सरल मामला जावैक का उपयोग करके संकलित नहीं करता है।

चूंकि जावा संकलित समय पर नहीं जानता है कि T क्या है, यह गारंटी नहीं दे सकता कि T<String> बिल्कुल सार्थक है।उदाहरण के लिए यदि आप एक Foo<BufferedImage> बनाया, bar हस्ताक्षर

public BufferedImage<String> bar() 

जो अतर्कसंगत है होगा। चूंकि जेनेरिक T एस के साथ Foo एस को तुरंत चालू करने के लिए आपको मजबूर करने के लिए कोई तंत्र नहीं है, इसलिए यह संकलित करने से इंकार कर देता है।

5

आदेश में एक प्रकार पैरामीटर पारित करने के लिए में, प्रकार परिभाषा घोषित करने के लिए (यह सामान्य हो गया है) है कि यह एक स्वीकार करता है। जाहिर है, आपका F एक सामान्य प्रकार नहीं है।

अद्यतन: लाइन

F<Fix<F>> in; 

जो एक प्रकार पैरामीटर, है जिसका मूल्य Fix है, जो अपने आप में एक प्रकार पैरामीटर स्वीकार करता है स्वीकार करता है प्रकार F के एक चर वाणी, जिसका मूल्य F है। F आपके उदाहरण में भी परिभाषित नहीं किया गया है। मुझे लगता है कि आप चाहते हो सकता है

Fix<F> in; 

कि तुम प्रकार Fix (प्रकार तुमने अपने उदाहरण में परिभाषित) जो आप मूल्य F के साथ एक प्रकार पैरामीटर गुजर रहे हैं करने के लिए के एक चर दे देंगे। चूंकि Fix को एक प्रकार पैरामीटर स्वीकार करने के लिए परिभाषित किया गया है, यह काम करता है।

अद्यतन 2: अपने शीर्षक पढ़ना, और अब मुझे लगता है कि आप "Towards Equal Rights for Higher-Kinded Types" (पीडीएफ चेतावनी) में प्रस्तुत किया दृष्टिकोण के समान कुछ करने के लिए प्रयास कर रहे हों। यदि ऐसा है, तो जावा इसका समर्थन नहीं करता है, लेकिन आप स्कैला को आजमा सकते हैं।

+0

क्या आप कृपया थोड़ा विस्तार कर सकते हैं? मैंने टाइप प्रकार को स्वीकार करने के लिए प्रकार घोषित कर दिया है - को ठीक करें। या यह तुम्हारा मतलब क्या नहीं है? – Martijn

+0

लेकिन आपके द्वारा चुने गए प्रकार - > - सामान्य नहीं है; यह केवल फिक्स के लिए काम करता है - आपको इसे टाइप करना चाहिए, निश्चित रूप से? – sanbikinoraion

+0

वह पेपर दिलचस्प है - धन्यवाद! – Martijn

0

यह रूप में अगर आप की तरह कुछ चाहते हो सकता है दिखता है: (। इसके जेनरिक के बारे में Enum वर्ग देखें, और सवाल)

public class Fix<F extends Fix<F>> { 
    private F in; 
} 

+0

हाय टॉम, वह समाधान वास्तव में दिलचस्प लग रहा है लेकिन मुझे वास्तव में अभी तक यह नहीं मिलता है कि यह क्या करता है। क्या एफ पर कुछ पदानुक्रम लगाया नहीं है? मैं ऐसा नहीं करना चाहता - मैं एफ से पूछता हूं कि यह अभी भी एक प्रकार का तर्क पूरा होने के लिए प्राप्त करता है। – Martijn

+0

यदि मामला है, तो जावा में ऐसा करना संभव नहीं है जो आप चाहते हैं - भाषा पर्याप्त अभिव्यक्तिपूर्ण नहीं है। – Chii

+0

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

24

शायद आप स्कैला को आजमा सकते हैं, जो कि जेएमवी पर चल रही एक कार्यात्मक भाषा है, जो उच्च-प्रकार के जेनरिक का समर्थन करता है।


[Rahul G द्वारा संपादित]

यहां अपने विशिष्ट उदाहरण मोटे तौर पर स्काला करने के लिए अनुवाद है:

trait Expr[+A] 

trait FixExpr { 
    val in: Expr[FixExpr] 
} 

trait Fix[F[_]] { 
    val in: F[Fix[F]] 
} 
1

फिर भी, जावा में higer-kinded जेनरिक एन्कोड करने के लिए तरीके हैं। कृपया, higher-kinded-java project पर एक नज़र डालें।

एक पुस्तकालय के रूप में इस का उपयोग करते हुए, तो आप इस तरह अपने कोड को संशोधित कर सकते हैं:

public class Fix<F extends Type.Constructor> { 
    Type.App<F, Fix<F>> in; 
} 

आप शायद अपने Expr वर्ग

@GenerateTypeConstructor 
public class Expr<S> { 
    // ... 
} 

यह एनोटेशन ExprTypeConstructor वर्ग उत्पन्न करने के लिए एक @GenerateTypeConstructor एनोटेशन जोड़ने चाहिए। अब आप इस तरह Expr के अपने फिक्स की प्रक्रिया कर सकते हैं:

class Main { 
    void run() { 
     runWithTyConstr(ExprTypeConstructor.get); 
    } 

    <E extends Type.Constructor> void runWithTyConstr(ExprTypeConstructor.Is<E> tyConstrKnowledge) { 
     Expr<Fix<E>> one = Expr.lit(1); 
     Expr<Fix<E>> two = Expr.lit(2); 

     // convertToTypeApp method is generated by annotation processor 
     Type.App<E, Fix<E>> oneAsTyApp = tyConstrKnowledge.convertToTypeApp(one); 
     Type.App<E, Fix<E>> twoAsTyApp = tyConstrKnowledge.convertToTypeApp(two); 

     Fix<E> oneFix = new Fix<>(oneAsTyApp); 
     Fix<E> twoFix = new Fix<>(twoAsTyApp); 

     Expr<Fix<E>> addition = Expr.add(oneFix, twoFix); 
     process(addition, tyConstrKnowledge); 
    } 

    <E extends Type.Constructor> void process(
      Fix<E> fixedPoint, 
      ExprTypeConstructor.Is<E> tyConstrKnowledge) { 

     Type.App<E, Fix<E>> inTyApp = fixedPoint.getIn(); 

     // convertToExpr method is generated by annotation processor 
     Expr<Fix<E>> in = tyConstrKnowledge.convertToExpr(inTyApp); 

     for (Fix<E> subExpr: in.getSubExpressions()) { 
      process(subExpr, tyConstrKnowledge); 
     } 
    } 

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