সি # ইন্টারফেসের সাথে হাস্কেল টাইপক্লাস প্রয়োগ করুন


13

আমি হাস্কেলের ধরণের ক্লাস এবং সি # এর ইন্টারফেসগুলির সাথে তুলনা করার চেষ্টা করছি। মনে করুন একটি আছে Functor

Haskell,:

class Functor f where
  fmap :: (a -> b) -> f a -> f b

সি # তে এই ধরণের শ্রেণিটি ইন্টারফেস হিসাবে কীভাবে প্রয়োগ করা যায়?

আমি যা চেষ্টা করেছি:

interface Functor<A, B>
{
    F<B> fmap(Func<A, B> f, F<A> x);
}

এটি অবৈধ বাস্তবায়ন এবং আমি আসলে জেনেরিক Fপ্রকারের সাথে জড়িত যা দ্বারা ফিরে আসা উচিত fmap। কীভাবে এটি সংজ্ঞায়িত করা উচিত এবং কোথায়?

Functorসি # তে বাস্তবায়ন করা কি অসম্ভব এবং কেন? বা অন্য কোন পদ্ধতির হতে পারে?


8
: এরিক Lippert কিভাবে সি # 'গুলি টাইপ সিস্টেম সত্যিই Functors উচ্চতর kinded প্রকৃতি সমর্থন করার জন্য যথেষ্ট হিসাবে এই উত্তর Haskell, দ্বারা সংজ্ঞায়িত নয় সম্পর্কে একটু আলোচনা stackoverflow.com/a/4412319/303940
KChaloux

1
এটি প্রায় 3 বছর আগে ছিল। কিছু পরিবর্তন হয়েছে?
3

4
সি # তে এটি সম্ভব করার জন্য কোনও কিছুই পরিবর্তিত হয়নি, এবং ভবিষ্যতে এর সম্ভাবনাও আমি মনে করি না
জে কে।

উত্তর:


8

সি # এর টাইপ সিস্টেমে ইন্টারফেস হিসাবে প্রকারের ক্লাসগুলি যথাযথভাবে প্রয়োগ করতে প্রয়োজনীয় কয়েকটি বৈশিষ্ট্য নেই।

আসুন আপনার উদাহরণ দিয়ে শুরু করা যাক, তবে কীটি টাইপক্লাসটি কী এবং কী করে তার একটি সম্পূর্ণ বিবরণ প্রদর্শন করছে এবং তারপরে সেগুলিকে সি # বিটে মানচিত্র দেওয়ার চেষ্টা করছে।

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 এর অন্তর্নিহিত টাইপ সিস্টেমে কেবল এমন ধারণা নেই।


2
আমি হাস্কেল (কেবলমাত্র স্ট্যান্ডার্ড এমএল) তে খুব পারদর্শী নই তাই এর ফলে কতটা পার্থক্য হয় তা আমি জানি না, তবে সি # তে যোগফলগুলি এনকোড করা সম্ভব
ডোভাল

5

আপনার যা দরকার তা দুটি শ্রেণি, একটি উচ্চতর অর্ডার জেনেরিক (ফান্টেক্টর) মডেল করা এবং একটি ফ্রি মান এ সমন্বিত ফান্টারের মডেল করা

interface F<Functor> {
   IF<Functor, A> pure<A>(A a);
}

interface IF<Functor, A> where Functor : F<Functor> {
   IF<Functor, B> pure<B>(B b);
   IF<Functor, B> map<B>(Func<A, B> f);
}

সুতরাং যদি আমরা অপশন মোনাড ব্যবহার করি (কারণ সমস্ত মনড ফান্টেক্টর)

class Option : F<Option> {
   IF<Option, A> pure<A>(A a) { return new Some<A>(a) };
}

class OptionF<A> : IF<Option, A> {
   IF<Option, B> pure<B>(B b) {
      return new Some<B>(b);
   }

   IF<Option, B> map<B>(Func<A, B> f) {
       var some = this as Some<A>;
       if (some != null) {
          return new Some<B>(f(some.value));
       } else {
          return new None<B>();
       }
   } 
}

তারপরে আপনার যখন প্রয়োজন হয় তখন IF <অপশন, বি> থেকে কিছু <A> তে রূপান্তর করতে আপনি স্থিতিশীল এক্সটেনশন পদ্ধতিগুলি ব্যবহার করতে পারেন


আমি সঙ্গে সমস্যা আছে pureজেনেরিক functor ইন্টারফেসে: কম্পাইলার এ অভিযোগ IF<Functor, A> pure<A>(A a);সঙ্গে "টাইপ Functorটাইপ প্যারামিটার হিসাবে ব্যবহার করা যাবে না Functorপদ্ধতির জেনেরিক ধরনের IF<Functor, A>আছে কোন বক্সিং রূপান্তর বা টাইপ প্যারামিটার রূপান্তর হয়। Functorথেকে F<Functor>।" এটার মানে কি? এবং কেন আমাদের pureদুটি জায়গায় সংজ্ঞা দেওয়া উচিত ? তদুপরি, pureস্থির হওয়া উচিত না ?
নিরিল

1
ওহে. আমি মনে করি কারণ ক্লাস ডিজাইনের সময় আমি মোনাড এবং মোনাড ট্রান্সফর্মারগুলির দিকে ইঙ্গিত করছিলাম। মোনাদ ট্রান্সফর্মার, যেমন অপশনটি মোনাদ ট্রান্সফর্মার (হাসেল ইন ম্যাসিটি) সি # তে অপশনটি <এম, এ> হিসাবে সংজ্ঞায়িত করা হয়েছে যেখানে এম অন্য জেনেরিক মনড। এম <অপশন <এ>> টাইপের একটি মোনাডে অপশনটি মোনাড ট্রান্সফর্মার বাক্সগুলি রয়েছে, তবে যেহেতু সি # তে উচ্চ ধরণের টাইপ নেই, তাই অপশনটি.ম্যাপ এবং অপশনটি.বাইন্ড কল করার সময় আপনার উচ্চতর ধরণের এম মোনাড ইনস্ট্যান্ট করার একটি উপায় প্রয়োজন। স্থিতিশীল পদ্ধতিগুলি কার্যকর হয় না কারণ আপনি কোনও মোনাড এম এর জন্য এমপিউর (এ এ) কল করতে পারবেন না
ডেট্রিয়াসএক্সেই
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.