2010-02-09 14 views
18

क्या एफ # में सी # जैसी ही समस्या है जहां आप सीधे सामान्य प्रकार के अंकगणितीय ऑपरेटरों का उपयोग नहीं कर सकते हैं?क्या एफ # में सामान्य अंकगणितीय समर्थन है?

क्या आप एक सामान्य योग फ़ंक्शन लिख सकते हैं जो अंकगणितीय जोड़ का समर्थन करने वाले किसी भी मान के योग को वापस कर देगा?

उत्तर

4

एफ # इसके लिए कुछ सीमित समर्थन है। एक अच्छे सामान्य समाधान में टाइप क्लास शामिल होते हैं, जो सामान्य रूप से सीएलआर द्वारा समर्थित नहीं होते हैं, या विशेष रूप से एफ #।

एफ # ने 'स्थैतिक सदस्य बाधाओं' और 'इनलाइन' कार्यों का उपयोग करके अंकगणितीय ऑपरेटरों को अधिभारित किया है। यह जादू है जो उदा। + ऑपरेटर int एस और float दोनों पर काम करने के लिए ऑपरेटर। आप inline फ़ंक्शन लिख सकते हैं जिनके कार्यान्वयन गणित ऑपरेटरों में अंतर्निहित हैं और कुछ प्रगति करते हैं, लेकिन सामान्य रूप से ऐसा करने में गैर-तुच्छ है। आप उदाहरण की जांच कर सकते हैं उदा। स्रोत कोड को Array.sum (FSharp.Core में array.fs में) F # स्रोत वितरण में जो महसूस करने के लिए सीटीपी के साथ आता है।

भी देखें 'स्थिर सदस्य की कमी' और 'अनुकरण प्रकार वर्गों' इस जवाब का हिस्सा:

http://msdn.microsoft.com/en-us/library/ee370581(VS.100).aspx

तरह

Functions with generic parameter types

के साथ ही पुस्तकालय के विभिन्न बिट्स http://msdn.microsoft.com/en-us/library/ee340262(VS.100).aspx

2

सबसे अच्छा तंत्र जिसे मैं निष्पादित करने के बारे में जानता हूं जेनेरिक अंकगणित प्रकार वर्ग वर्ग है, जो दुख की बात है न तो सी #, एफ #, और न ही सामान्य समर्थन में नेट रनटाइम। हालांकि, अगर आप उन्हें अपने हाथ से अनुकरण कर सकते हैं, इस ब्लॉग पोस्ट में उल्लेख किया:

Type Classes Are The Secret Sauce

कि तकनीक सी # 2.0 या बाद में काम करते हैं (अनाम प्रतिनिधियों/lambdas का प्रयोग करके) चाहिए।

अक्सर लोगों, एक जोड़ी समस्याओं

  1. आप की घोषणा नहीं कर सकते हैं कि मौजूदा प्रकार एक इंटरफ़ेस को लागू में इंटरफेस की ओर रुख, लेकिन इतना आपको लगता है कि इंटरफेस के कहने को परिभाषित नहीं कर सकते हैं चलाने के लिए पूर्णांक जैसे प्रकार में बनाया ।
  2. इंटरफेस विधियों के लिए अन्य तर्कों के प्रकार को बाधित नहीं कर सकता है।

एक इंटरफ़ेस घोषित करता है कि, सभी कार्यान्वयन के लिए, उस इंटरफ़ेस पर सभी विधियां समान अंतर्निहित 'यह' पैरामीटर प्रकार लेती हैं। यदि फू कुछ इंटरफ़ेस लागू करता है, तो स्पष्ट रूप से 'यह' पैरामीटर उस कार्यान्वयन के लिए Foo प्रकार का होना चाहिए। लेकिन अन्य विधि पैरामीटर की आवश्यकता नहीं है भी प्रकार Foo का होना चाहिए।

Type classes आपको सभी पैरामीटर पैरामीटर पर इस प्रकार की बाधा निष्पादित करने की अनुमति देता है, न केवल पहले पैरामीटर।

जैसा कि पहले उद्धृत आलेख में बताया गया है, आप स्पष्ट तर्कों के रूप में फ़ंक्शन टेबल को पास करके टाइप क्लास का अनुकरण कर सकते हैं।

(सामुदायिक विकि: उस लेख सी # में यहाँ अनुवाद से एक उदाहरण पोस्ट करेंगे, लेकिन घना explaination के साथ समय से बाहर भाग)

4

आप कुछ इस तरह कर सकता है।

let inline sum<'a when 'a : (static member (+) : 'a -> 'a -> 'a)> a b = 
    a + b 

let result = sum<int> 3 4 

लेकिन अगर मैं let result = sum 3 4 कोशिश मैं "type ambiguity inherent in the use of the operator '(+)'"

+2

मैंने सोचा कि आपको एफ # में स्थिर बाधाओं का उपयोग करते समय ''ए' के ​​बजाय'^a' का उपयोग करने की आवश्यकता है, लेकिन मैं गलत हो सकता हूं ... –

+0

इस मामले में दोनों काम करते हैं। – gradbot

+5

इस विशेष मामले में, आपको जेनेरिक पैरामीटर या बाधाओं को निर्दिष्ट करने की भी आवश्यकता नहीं है क्योंकि उन्हें अनुमान लगाया जा सकता है: 'इनलाइन को बी = ए + बी' – kvb

8

ब्रायन उल्लेख किया है, वहाँ है त्रुटि मिलती है कुछ में निर्मित सामान्य arithmethic के लिए समर्थन और आप 'स्थिर की कमी' है कि आपकी कुछ सामान्य निर्धारित करने की अनुमति का उपयोग कर सकते स्वयं कार्य करता है (हालांकि यह थोड़ा सीमित है)।

इसके अलावा, आप गतिशील 'न्यूमेरिक एसोसिएशन' का भी उपयोग कर सकते हैं, जो किसी फ़ंक्शन में उपयोग करते समय थोड़ा धीमा होता है, लेकिन इसका उपयोग आपके स्वयं के वेक्टर या मैट्रिक्स प्रकार को परिभाषित करने के लिए उदाहरण के लिए किया जा सकता है। यहां एक उदाहरण दिया गया है:

#r "FSharp.PowerPack.dll" 
open Microsoft.FSharp.Math 

let twoTimesLarger (n:'a) (m:'a) = 
    let ops = GlobalAssociations.GetNumericAssociation<'a>() 
    let sel = if ops.Compare(n, m) > 0 then n else m 
    ops.Multiply(sel, ops.Add(ops.One, ops.One)) 

हमें पहले एफ # पावरपैक लाइब्रेरी का संदर्भ देने की आवश्यकता है जिसमें कार्यक्षमता शामिल है। फिर हम एक सामान्य कार्य को हस्ताक्षर 'a -> 'a -> 'a के साथ परिभाषित करते हैं। पहली पंक्ति गतिशील रूप से 'a के साथ काम करने के लिए संख्यात्मक संचालन पाती है (यह अनिवार्य रूप से कुंजी के रूप में टाइप के साथ कुछ लुकअप तालिका का उपयोग करती है)। फिर आप गुणात्मक, अतिरिक्त (Multiply, Add) और कई अन्य चीज़ों को करने के लिए संख्यात्मक संचालन ऑब्जेक्ट के तरीकों का उपयोग कर सकते हैं। समारोह किसी भी संख्या के साथ काम करता है:

twoTimesLarger 3 4 
twoTimesLarger 2.3 2.4 
twoTimesLarger "a" "b" // Throws an exception! 

जब आप अपने खुद के संख्यात्मक प्रकार को परिभाषित है, तो आप अपने सांख्यिक संचालन को परिभाषित करने और उन्हें रजिस्टर GlobalAssociations.RegisterNumericAssociation का उपयोग कर सकते हैं। मेरा मानना ​​है कि इसका मतलब यह भी है कि आप परिचालन पंजीकृत करने के बाद अंतर्निहित F # Matrix<YourType> और Vector<YourType> का उपयोग करने में सक्षम होंगे।

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