C # प्रकार की प्रणाली में इंटरफ़ेस के रूप में प्रकार की कक्षाओं को ठीक से लागू करने के लिए आवश्यक कुछ सुविधाओं का अभाव है।
आइए अपने उदाहरण के साथ शुरू करें, लेकिन कुंजी एक फुलका खाता दिखा रही है कि टाइपकास्ट क्या है और क्या करता है, और फिर उन सी # बिट्स को मैप करने की कोशिश कर रहा है।
class Functor f where
fmap :: (a -> b) -> f a -> f b
यह प्रकार वर्ग परिभाषा है, या इंटरफ़ेस के समान है। अब एक प्रकार की परिभाषा देखते हैं और यह उस प्रकार के वर्ग का कार्यान्वयन है।
data Awesome a = Awesome a a
instance Functor Awesome where
fmap f (Awesome a1 a2) = Awesome (f a1) (f a2)
अब हम बहुत स्पष्ट रूप से प्रकार वर्गों का एक अलग तथ्य देख सकते हैं जो आपके पास इंटरफेस के साथ नहीं हो सकता है। प्रकार वर्ग का कार्यान्वयन प्रकार की परिभाषा का हिस्सा नहीं है। C # में, इंटरफ़ेस लागू करने के लिए, आपको इसे उस प्रकार की परिभाषा के एक भाग के रूप में लागू करना होगा जो इसे लागू करता है। इसका मतलब है कि आप एक प्रकार के लिए एक इंटरफ़ेस लागू नहीं कर सकते हैं जिसे आप खुद को लागू नहीं करते हैं, हालांकि हास्केल में आप किसी भी प्रकार के लिए एक प्रकार की कक्षा को लागू कर सकते हैं जिसकी आपके पास पहुंच है।
यह शायद तुरंत सबसे बड़ा है, लेकिन एक और काफी महत्वपूर्ण अंतर है जो सी # समतुल्य वास्तव में लगभग काम नहीं करता है, और आप इसे अपने प्रश्न में छू रहे हैं। यह बहुरूपता के बारे में है। इसके अलावा कुछ अपेक्षाकृत सामान्य बातें हैं हास्केल आपको उन प्रकार के वर्गों के साथ करने की अनुमति देता है जो विशेष रूप से अनुवाद नहीं करते हैं जब आप अस्तित्वगत प्रकारों में जेनेरिकवाद की मात्रा या जेनेरिक एडीटी जैसे अन्य जीएचसी एक्सटेंशनों को देखना शुरू करते हैं।
आप देखते हैं, हास्केल के साथ आप फंक्शंस को परिभाषित कर सकते हैं
data List a = List a (List a) | Terminal
data Tree a = Tree val (Tree a) (Tree a) | Terminal
instance Functor List where
fmap :: (a -> b) -> List a -> List b
fmap f (List a Terminal) = List (f a) Terminal
fmap f (List a rest) = List (f a) (fmap f rest)
instance Functor Tree where
fmap :: (a -> b) -> Tree a -> Tree b
fmap f (Tree val Terminal Terminal) = Tree (f val) Terminal Terminal
fmap f (Tree val Terminal right) = Tree (f val) Terminal (fmap f right)
fmap f (Tree val left Terminal) = Tree (f val) (fmap f left) Terminal
fmap f (Tree val left right) = Tree (f val) (fmap f left) (fmap f right)
तब खपत में आपका एक कार्य हो सकता है:
mapsSomething :: Functor f, Show a => f a -> f String
mapsSomething rar = fmap show rar
यहाँ समस्या है। C # में आप इस फंक्शन को कैसे लिखते हैं?
public Tree<a> : Functor<a>
{
public a Val { get; set; }
public Tree<a> Left { get; set; }
public Tree<a> Right { get; set; }
public Functor<b> fmap<b>(Func<a,b> f)
{
return new Tree<b>
{
Val = f(val),
Left = Left.fmap(f);
Right = Right.fmap(f);
};
}
}
public string Show<a>(Showwable<a> ror)
{
return ror.Show();
}
public Functor<String> mapsSomething<a,b>(Functor<a> rar) where a : Showwable<b>
{
return rar.fmap(Show<b>);
}
इसलिए सी # संस्करण के साथ कुछ गलत बातें हैं, एक बात के लिए मैं निश्चित भी नहीं हूं कि यह आपको <b>
क्वालिफायर का उपयोग करने की अनुमति देगा जैसे मैंने वहां किया था, लेकिन इसके बिना मैं निश्चित हूं कि यह Show<>
उचित रूप से प्रेषण नहीं होगा। और पता लगाने के लिए संकलन; मैंने नहीं किया)।
हालाँकि इससे भी बड़ी समस्या यह है कि हास्केल में ऊपर के विपरीत जहां हमने अपने Terminal
प्रकार के हिस्से के रूप में परिभाषित किया था और फिर सी # उपयुक्त पैरामीट्रिक पॉलीमॉर्फिज्म की कमी के कारण टाइप के स्थान पर प्रयोग करने योग्य था (जो सुपर स्पष्ट हो जाता है जैसे ही आप इंटरॉप करने की कोशिश करते हैं F # के साथ C #) आप स्पष्ट रूप से या साफ-साफ भेद नहीं कर सकते हैं कि दाएं या बाएं Terminal
s हैं या नहीं । सबसे अच्छा आप उपयोग कर सकते हैं null
, लेकिन क्या होगा यदि आप एक मूल्य प्रकार बनाने की कोशिश कर रहे हैं Functor
या उस मामले में Either
जहां आप दो प्रकारों को अलग कर रहे हैं कि दोनों एक मूल्य ले? अब आपको एक प्रकार का उपयोग करना होगा और अपने भेदभाव को मॉडल करने के लिए जांचने और स्विच करने के लिए दो अलग-अलग मूल्य होंगे?
उचित योग प्रकारों, यूनियन प्रकारों, ADTs की कमी, जो भी आप उन्हें कॉल करना चाहते हैं, वह वास्तव में बहुत कुछ बनाता है जो टाइपकालेज़ आपको देते हैं क्योंकि वे दिन के अंत में आपको कई प्रकारों (कंस्ट्रक्टर्स) को एक प्रकार का मानते हैं। और .NET की अंतर्निहित प्रकार प्रणाली में ऐसी कोई अवधारणा नहीं है।