সি # এর টাইপ সিস্টেমে ইন্টারফেস হিসাবে প্রকারের ক্লাসগুলি যথাযথভাবে প্রয়োগ করতে প্রয়োজনীয় কয়েকটি বৈশিষ্ট্য নেই।
আসুন আপনার উদাহরণ দিয়ে শুরু করা যাক, তবে কীটি টাইপক্লাসটি কী এবং কী করে তার একটি সম্পূর্ণ বিবরণ প্রদর্শন করছে এবং তারপরে সেগুলিকে সি # বিটে মানচিত্র দেওয়ার চেষ্টা করছে।
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)
এখন আমরা স্পষ্টতই টাইপ ক্লাসগুলির একটি স্বতন্ত্র ঘটনা দেখতে পাই যা আপনার ইন্টারফেসের সাথে থাকতে পারে না । প্রকারের শ্রেণীর বাস্তবায়ন ধরণের সংজ্ঞাটির অংশ নয়। সি # তে, একটি ইন্টারফেস প্রয়োগ করতে, আপনাকে অবশ্যই এটি প্রয়োগ করে এমন সংজ্ঞাটির একটি অংশ হিসাবে এটি প্রয়োগ করতে হবে। এর অর্থ আপনি কোনও প্রকারের জন্য কোনও ইন্টারফেস প্রয়োগ করতে পারবেন না যা আপনি নিজেকে প্রয়োগ করেন না, তবে হাসকেলে আপনি যে কোনও ধরণের অ্যাক্সেস পেয়েছেন তার জন্য টাইপ শ্রেণি প্রয়োগ করতে পারেন।
এটি সম্ভবত তাত্ক্ষণিকতম বৃহত্তম, তবে আরও একটি উল্লেখযোগ্য তাত্পর্য রয়েছে যা সি # সমতুল্য সত্যিকারের মতো প্রায় কাজ করে না এবং আপনি আপনার প্রশ্নে এটি স্পর্শ করছেন। এটি পলিমারফিজম সম্পর্কে। এছাড়াও কিছু অপেক্ষাকৃত জেনেরিক জিনিস রয়েছে যা হ্যাস্কেল আপনাকে টাইপ শ্রেণীর সাথে করতে দেয় যা পুরোপুরি অনুবাদ করে না বিশেষত যখন আপনি অস্তিত্বমূলক প্রকারের জেনেরিকতার পরিমাণ বা জেনেরিক এডিটিগুলির মতো অন্যান্য জিএইচসি এক্সটেনশনের দিকে তাকাতে শুরু করেন।
আপনি দেখুন, হাস্কেল দিয়ে আপনি ফান্টেক্টর সংজ্ঞায়িত করতে পারেন
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
এর মধ্যেই সমস্যা রয়েছে। সি # তে আপনি এই ফাংশনটি কীভাবে লিখবেন?
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
ধরণের অংশ হিসাবে আমাদের সংজ্ঞা দেওয়া হয়েছিল এবং টাইপের জায়গায় ব্যবহারের যোগ্য, সি # এর উপযুক্ত প্যারামেট্রিক পলিমারফিজমের অভাবের কারণে (যা আপনি ইন্টারপ করার চেষ্টা করার সাথে সাথেই সুপার স্পষ্ট হয়ে ওঠে সি # সহ এফ #) আপনি ডান বা বাম হয় তা পরিষ্কার বা পরিষ্কারভাবে আলাদা করতে পারবেন না Terminal
। আপনি সবচেয়ে ভাল ব্যবহার করতে পারেন null
তবে আপনি যদি কোনও মান টাইপ একটি করার চেষ্টা করছেন Functor
বা Either
যেখানে আপনি দুটি প্রকারের উভয়কেই আলাদা করে রাখেন এমন মান ব্যবহার করেন? আপনার বৈষম্যকে মডেল করার জন্য এখন আপনাকে এক ধরণের ব্যবহার করতে হবে এবং দুটি আলাদা মান থাকতে হবে?
যথাযথ পরিমাণের প্রকার, ইউনিয়নের ধরণ, এডিটিগুলির অভাব, আপনি যা কিছু কল করতে চান তা প্রকৃতপক্ষে টাইপক্ল্যাশগুলি যা দেয় তা আপনাকে অনেকটাই দূরে সরিয়ে দেয় কারণ দিনের শেষে তারা আপনাকে একাধিক ধরণের (কনস্ট্রাক্টর) একক ধরণের হিসাবে আচরণ করতে দেয়, এবং .NET এর অন্তর্নিহিত টাইপ সিস্টেমে কেবল এমন ধারণা নেই।