2010-02-14 16 views
6

मेरा प्रश्न कुछ हद तक इस से संबंधित है - Functions with generic parameter types - लेकिन मैं काफी कुछ नहीं कर सकता कि मैं क्या चाहता हूं।एफ #: ओवरलोडिंग फ़ंक्शन

मैं एक परिभाषित करना चाहते हैं विभिन्न सी # वर्गों पर वंशज 'तो जैसे' वंश के लिए कॉल रैप करने के लिए कार्य करते हैं ':

जाने वंश का नाम (xDocument: XDocument) = xDocument.Descendants नाम

सन्तान जाने नाम (xElement: XElement) = xElement.Descendants नाम

यह दृष्टिकोण काम नहीं करता है क्योंकि हमारे पास 'वंश' की डुप्लिकेट परिभाषा है।

मैंने सोचा कि यह इनलाइन समारोह का उपयोग करें और स्थिर निम्नलिखित विधि को परिभाषित करने के मापदंडों को हल करने के बजाय यह करने के लिए संभव हो जाएगा:

let inline descendants name (xml : ^x when ^x : (member Descendants : XName -> seq<XElement>)) = 
    xml.Descendants name 

लेकिन मैं जब ऐसा करने की कोशिश कर रहा है इस त्रुटि हो रही है :

इस कार्यक्रम बिंदु से पहले जानकारी के आधार पर अनिश्चित प्रकार की वस्तु पर लुकअप। ऑब्जेक्ट के प्रकार को बाधित करने के लिए इस प्रोग्राम बिंदु से पहले एक प्रकार की एनोटेशन की आवश्यकता हो सकती है। यह लुकअप को हल करने की अनुमति दे सकता है।

क्या कोई तरीका है कि मैं वह दूसरा कार्य लिख सकता हूं जो मैं चाहता हूं?

उत्तर

4

संकलित नीचे कोड (और स्थैतिक सदस्य बाधा कार्यों को कॉल करने के लिए आवश्यक वाक्यविन्यास का सुझाव है)।

open System.Xml.Linq 

let descendants1 name (xDocument:XDocument) = xDocument.Descendants name 

let descendants2 name (xElement:XElement) = xElement.Descendants name 

let inline descendants name (xml : ^x when ^x : (member Descendants : XName -> seq<XElement>)) = 
    (^x : (member Descendants : XName -> seq<XElement>) (xml,name)) 

let xd = XDocument.Load("http://www.somexml.com") 
let ds = descendants (XName.op_Implicit "foo") xd 
let xe = XElement.Load("http://www.somexml.com") 
let eds = descendants (XName.op_Implicit "foo") xe 
14

सामान्य शब्दों में, मुझे लगता है कि हैट-प्रकार इस तरह के ^x के रूप में हो सकता है बहुत ज्यादा (कम से कम, अतः पर उनके बारे में सवालों की संख्या से पहचानने) का इस्तेमाल किया जा रहा है। यह एक शक्तिशाली विशेषता है, लेकिन यह वास्तव में जेनेरिक अंकगणित के साथ समस्याओं को हल करने के लिए मुख्य रूप से डिजाइन किया गया था। मुझे लगता है कि वे एफ # कार्यक्रमों को अनावश्यक रूप से जटिल बना सकते हैं।

तुम सिर्फ XDocument और XElement के साथ काम कर रहे हैं, तो इस सवाल का जवाब बहुत सरल है, क्योंकि आप XContainer उपयोग कर सकते हैं जो उनके आम आधार वर्ग है और Descendants विधि है:

let descendants name (xml:XContainer) = xml.Descendants(name) 

// Both of these will work fine 
descendants (XName.Get "foo") xd 
descendants (XName.Get "foo") xe 

आप बंद हो जाए तो एक आम आधार वर्ग है, तो आप निश्चित रूप से ^a प्रकार का उपयोग कर सकते हैं, लेकिन आप भी सामान्य से अधिक भार है, जो एफ # में संभव है, लेकिन वस्तु प्रकार के सदस्यों के लिए ही काम करता है इस्तेमाल कर सकते हैं:

type Xml = 
    static member Descendants(name, x:XDocument) = x.Descendants(name) 
    static member Descendants(name, x:SomeOtherClass) = x.SomeOtherDescendants(name) 

// The usage looks like this: 
Xml.Descendants(XName.Get "foo", xd) 
Xml.Descendants(XName.Get "foo", new SomeOtherClass()) 

(चूंकि आपने एक ऐसे प्रश्न के साथ एक प्रश्न का संदर्भ दिया है जो पहले से ही दिखाता है कि ओवरलोडिंग सदस्यों के साथ काम करता है, यह शायद आपके लिए कुछ भी नया नहीं है। लेकिन यह उन लोगों के लिए उपयोगी हो सकता है जो भविष्य में यह प्रश्न पाएंगे)।

+0

आह मुझे एहसास नहीं हुआ कि ओवरलोडिंग केवल सदस्यों के लिए ही काम करती है, जाहिर है कि अन्य पोस्ट को पर्याप्त रूप से पर्याप्त नहीं पढ़ा! यह भी नहीं उठाया कि वे दोनों एक्सकॉन्टेनर से विरासत में हैं, इसलिए धन्यवाद, यह एक बेहतर समाधान है –

+0

मैंने सामान्य अधिभार वास्तव में कोशिश की और संकलक कहता है कि दो सदस्यों को 'descendants' कहा जाता है, उसी तर्क के साथ –

+0

कुछ पहले संस्करण, एफ # कंपाइलर की आवश्यकता है '[<ओवरलोड आईडी ("कुछ नाम")>]' ओवरलोडिंग के दौरान इस्तेमाल किया जाना चाहिए, लेकिन मुझे यकीन नहीं है कि यह किस संस्करण में हटा दिया गया था ... मैंने अभी एफ # आरसी में सरल उदाहरण की कोशिश की है (दो विधियां , दो तर्कों के साथ दोनों) और यह ठीक काम किया ('अधिभार आईडी के बिना)। –

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