র্যাঙ্ক টু টাইপসের উদ্দেশ্য কী?


110

আমি হাসকেলে আসলেই দক্ষ নই, সুতরাং এটি খুব সহজ প্রশ্ন হতে পারে।

র্যাঙ্ক 2 টিপগুলি কোন ভাষার সীমাবদ্ধতা সমাধান করে? হাস্কেলের মধ্যে ফাংশনগুলি ইতিমধ্যে বহুবিধ যুক্তিগুলি সমর্থন করে না?


এটি মূলত এইচএম টাইপ সিস্টেম থেকে পলিমারফিক ল্যাম্বদা ক্যালকুলাস ওরফে আপগ্রেড। λ2 / সিস্টেম এফ। মনে রাখবেন যে টাইপ অনুমান λ2 এ অনির্ধারিত।
পোস্টক্যাট

উত্তর:


116

হাস্কেলের মধ্যে কি ফাংশনগুলি ইতিমধ্যে বহুবৈচিত্র্য যুক্তি সমর্থন করে না?

তারা করে তবে কেবল 1 পদমর্যাদার This

উদাহরণস্বরূপ নীচের ফাংশনটি এই এক্সটেনশনটি ছাড়া টাইপ করা যাবে না কারণ gএর সংজ্ঞাতে বিভিন্ন যুক্তি ধরণের সাথে ব্যবহৃত হয় f:

f g = g 1 + g "lala"

মনে রাখবেন যে কোনও ফাংশনের যুক্তি হিসাবে পলিমারফিক ফাংশনটি পাস করা পুরোপুরি সম্ভব। সুতরাং মত map id ["a","b","c"]কিছু পুরোপুরি আইনী। তবে ফাংশনটি কেবল এটি মনোমরফিক হিসাবে ব্যবহার করতে পারে। উদাহরণস্বরূপ mapব্যবহার করেid যেমন এটি টাইপ ছিল String -> String। এবং অবশ্যই আপনি প্রদত্ত প্রকারের পরিবর্তে একটি সাধারণ মনোমরফিক ফাংশনও পাস করতে পারেন id। র‌্যাঙ্ক 2 টাইপ ব্যতীত কোনও ফাংশনের পক্ষে তার আর্গুমেন্টটি পলিমারফিক ফাংশন হওয়া আবশ্যক এবং এইভাবে পলিমারফিক ফাংশন হিসাবে এটি ব্যবহার করার কোনও উপায় নেই।


5
আমার উত্তরটির সাথে এটির সাথে সংযুক্ত কিছু শব্দ যুক্ত করতে: হাস্কেল ফাংশনটি বিবেচনা করুন f' g x y = g x + g y। এটির অনুমানযুক্ত র‌্যাঙ্ক -1 প্রকার forall a r. Num r => (a -> r) -> a -> a -> r। যেহেতু forall aফাংশন তীরগুলির বাইরে রয়েছে, কলকারীকে প্রথমে কোনও প্রকার বাছাই করতে হবে a; যদি তারা বাছাই করে Int, আমরা পাই f' :: forall r. Num r => (Int -> r) -> Int -> Int -> r, এবং এখন আমরা gযুক্তিটি স্থির করেছি যাতে এটি নিতে পারে Intতবে না String। আমরা যদি সক্ষম করে RankNTypesথাকি তবে আমরা f'প্রকারের সাথে মন্তব্য করতে পারি forall b c r. Num r => (forall a. a -> r) -> b -> c -> r। এটি ব্যবহার করতে পারবেন না, যদিও — কী হবে g?
লুইস ক্যাসিলাস

166

আপনি সিস্টেম এফ অধ্যয়ন না করা হলে উচ্চ-স্তরের পলিমারফিজম বোঝা শক্ত সরাসরি , কারণ হাস্কেল সরলতার স্বার্থে আপনার কাছ থেকে এর বিশদগুলি গোপন করার জন্য তৈরি করা হয়েছে।

তবে মূলত, মোটামুটি ধারণাটি হ'ল পলিমারফিক ধরণের ধরণের প্রকৃতপক্ষে a -> bহ্যাসকেলে তারা ফর্মটি রাখে না; বাস্তবে, এগুলি দেখতে সর্বদা সুস্পষ্ট কোয়ান্টিফায়ার সহ:

id :: a.a  a
id = Λtx:t.x

যদি আপনি "∀" চিহ্নটি না জানেন তবে এটি "সবার জন্য" হিসাবে পড়া হয়; ∀x.dog(x)মানে "সমস্ত এক্স এর জন্য, এক্স একটি কুকুর" " "Λ" হ'ল মূলধন ল্যাম্বদা, প্রকারের পরামিতিগুলিকে বিমূর্ত করার জন্য ব্যবহৃত হয়; দ্বিতীয় লাইনটি যা বলে তা হ'ল আইডি একটি ফাংশন যা একটি প্রকার নেয়t এবং তারপরে সেই ধরণের দ্বারা প্যারামিট্রাইজ করা একটি ফাংশন দেয়।

আপনি দেখতে পাচ্ছেন, সিস্টেম এফ-এ আপনি ঠিক এখনই idকোনও মানটির মতো কোনও ফাংশন প্রয়োগ করতে পারবেন না ; প্রথমে আপনাকে কোনও মানটিতে প্রয়োগ করা একটি λ-ফাংশন পেতে আপনাকে কোনও ধরণের Λ- ফাংশন প্রয়োগ করতে হবে। উদাহরণস্বরূপ:

tx:t.x) Int 5 = x:Int.x) 5
                  = 5

স্ট্যান্ডার্ড হাস্কেল (যেমন, হাস্কেল 98 এবং 2010) এই ধরণের কোয়ান্টিফায়ার, মূলধন ল্যাম্বডাস এবং টাইপ অ্যাপ্লিকেশন না রেখে আপনার জন্য এটি সহজ করে তোলে, তবে জিএইচসি যখন সংকলনের জন্য প্রোগ্রামটি বিশ্লেষণ করে তখন সেই দৃশ্যের পিছনে রাখে। (আমার বিশ্বাস, রানটাইম ওভারহেড ছাড়াই এটি সমস্ত সংকলন-কালীন স্টাফ।)

তবে হাস্কেলের এটির স্বয়ংক্রিয়ভাবে পরিচালনার অর্থ এটি ধরে নেওয়া হয় যে "∀" কোনও ফাংশন ("→") টাইপের বাম-হাতের শাখায় কখনই উপস্থিত হয় না। Rank2Typesএবং RankNTypesএই বিধিনিষেধগুলি বন্ধ করে দেয় এবং যেখানে সন্নিবেশ করানো হবে তার জন্য আপনাকে হাস্কেলের ডিফল্ট নিয়মগুলিকে ওভাররাইড করার অনুমতি দেয়forall

তুমি কেন এটা করতে চাও? কারণ পূর্ণ, সীমাহীন সিস্টেম এফ হেলা শক্তিশালী, এবং এটি প্রচুর শীতল স্টাফ করতে পারে। উদাহরণস্বরূপ, প্রকারের আড়ালকরণ এবং মড্যুলারিটি উচ্চ-স্তরের প্রকারগুলি ব্যবহার করে প্রয়োগ করা যেতে পারে। উদাহরণস্বরূপ নিম্নলিখিত র‌্যাঙ্ক -1 ধরণের (দৃশ্য সেট করার জন্য) একটি সরল পুরানো ফাংশন ধরুন:

f :: r.∀a.((a  r)  a  r)  r

ব্যবহার করতে f, কলকারীকে প্রথমে কোন ধরণের জন্য ব্যবহার করতে হবে তা চয়ন করতে হবে rএবং aতারপরে ফলাফলের ধরণের যুক্তি সরবরাহ করতে হবে । সুতরাং আপনি বাছাই করতে পারেন r = Intএবং a = String:

f Int String :: ((String  Int)  String  Int)  Int

তবে এখন এটি নিম্নলিখিত উচ্চ-স্তরের প্রকারের সাথে তুলনা করুন:

f' :: r.(∀a.(a  r)  a  r)  r

এই ধরণের একটি ফাংশন কীভাবে কাজ করে? ভাল, এটি ব্যবহার করার জন্য, প্রথমে আপনি কোন ধরণের জন্য ব্যবহার করবেন তা নির্দিষ্ট করে দিন r। বলুন আমরা বাছাই Int:

f' Int :: (∀a.(a  Int)  a  Int)  Int

কিন্তু এখন ∀aহয় ভিতরে ফাংশন তীর, যাতে আপনি কি ধরনের জন্য ব্যবহার করতে নিতে পারে না a; আপনার অবশ্যই f' Intউপযুক্ত ধরণের একটি function- ফাংশনে আবেদন করতে হবে । এর অর্থ হল যে প্রয়োগকারী f'কোন ধরণের aকল করতে হবে তা কল করার জন্য নয়f' । উচ্চ-স্তরের প্রকারগুলি ছাড়াই, বিপরীতে, কলার সর্বদা প্রকারগুলি চয়ন করে।

এটি কি জন্য দরকারী? ভাল, আসলে অনেক কিছুর জন্য, তবে একটি ধারণা হ'ল আপনি এটিকে অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিংয়ের মতো জিনিসগুলির মডেল করতে ব্যবহার করতে পারেন, যেখানে "অবজেক্টস" কিছু লুকানো ডেটা বান্ডিল করে এমন কিছু পদ্ধতি যা গোপন তথ্যগুলিতে কাজ করে। সুতরাং উদাহরণস্বরূপ, দুটি পদ্ধতির একটি অবজেক্ট — একটি যা প্রত্যাবর্তন করে Intএবং অন্যটি যা প্রত্যাবর্তন করে String, এই ধরণের মাধ্যমে প্রয়োগ করা যেতে পারে:

myObject :: r.(∀a.(a  Int, a -> String)  a  r)  r

কিভাবে কাজ করে? অবজেক্টটি কোনও ফাংশন হিসাবে বাস্তবায়িত হয় যার মধ্যে লুকানো ধরণের কিছু অভ্যন্তরীণ ডেটা থাকে a। বস্তুটি আসলে ব্যবহার করতে, তার ক্লায়েন্টরা একটি "কলব্যাক" ফাংশনে পাস করে যা বস্তু দুটি পদ্ধতির সাহায্যে কল করবে। উদাহরণ স্বরূপ:

myObject String a. λ(length, name):(a  Int, a  String). λobjData:a. name objData)

এখানে আমরা মূলত অবজেক্টের দ্বিতীয় পদ্ধতিটি আহ্বান করছি, যার ধরণটি a → Stringঅজানা a। ভাল, myObjectএর ক্লায়েন্টদের কাছে অজানা ; তবে এই ক্লায়েন্টরা স্বাক্ষর থেকে জানতে পারে যে তারা এটিতে দুটি ফাংশনের যে কোনও একটি প্রয়োগ করতে সক্ষম হবে এবং একটি Intবা একটি পাবেString

আসল হাস্কেলের উদাহরণস্বরূপ, নীচে কোডটি আমি লিখেছিলাম যা আমি নিজে শিখিয়েছি RankNTypes। এটি এমন একটি প্রকার প্রয়োগ করে ShowBoxযা কিছু শ্রেণিবদ্ধের সাথে তার Showশ্রেণীর উদাহরণের সাথে একত্রে কিছু বান্ডিল করে nd নোট করুন যে নীচে অবস্থিত উদাহরণে, আমি একটি তালিকা তৈরি করেছি ShowBoxযার প্রথম উপাদানটি একটি সংখ্যা থেকে তৈরি হয়েছিল, এবং দ্বিতীয়টি স্ট্রিং থেকে। যেহেতু প্রকারগুলি উচ্চ-র‌্যাঙ্কের প্রকারগুলি ব্যবহার করে আড়াল করা থাকে তাই এটি প্রকারের চেকিং লঙ্ঘন করে না।

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ImpredicativeTypes #-}

type ShowBox = forall b. (forall a. Show a => a -> b) -> b

mkShowBox :: Show a => a -> ShowBox
mkShowBox x = \k -> k x

-- | This is the key function for using a 'ShowBox'.  You pass in
-- a function @k@ that will be applied to the contents of the 
-- ShowBox.  But you don't pick the type of @k@'s argument--the 
-- ShowBox does.  However, it's restricted to picking a type that
-- implements @Show@, so you know that whatever type it picks, you
-- can use the 'show' function.
runShowBox :: forall b. (forall a. Show a => a -> b) -> ShowBox -> b
-- Expanded type:
--
--     runShowBox 
--         :: forall b. (forall a. Show a => a -> b) 
--                   -> (forall b. (forall a. Show a => a -> b) -> b)
--                   -> b
--
runShowBox k box = box k


example :: [ShowBox] 
-- example :: [ShowBox] expands to this:
--
--     example :: [forall b. (forall a. Show a => a -> b) -> b]
--
-- Without the annotation the compiler infers the following, which
-- breaks in the definition of 'result' below:
--
--     example :: forall b. [(forall a. Show a => a -> b) -> b]
--
example = [mkShowBox 5, mkShowBox "foo"]

result :: [String]
result = map (runShowBox show) example

পিএস: ExistentialTypesজিএইচসি কীভাবে আসে সে সম্পর্কে কারও মনে এই প্রশ্নটি পড়ে forall, আমি বিশ্বাস করি কারণ এর কারণ হ'ল কারণ তিনি এই ধরণের কৌশলটি পর্দার আড়ালে ব্যবহার করছেন।


2
খুব বিস্তৃত উত্তরের জন্য ধন্যবাদ! (যা ঘটনাক্রমে যথাযথ তত্ত্ব এবং সিস্টেম এফ শিখতেও আমাকে উদ্বুদ্ধ করেছিল)
আলেকসন্দর দিমিত্রভ

5
আপনার existsকীওয়ার্ড থাকলে আপনি একটি অস্তিত্বের ধরণের সংজ্ঞা দিতে পারেন (উদাহরণস্বরূপ) data Any = Any (exists a. a), যেখানে Any :: (exists a. a) -> Any। → প্রশ্ন ∀xP (x) এর → প্রশ্ন ≡ (∃xP (x) এর) ব্যবহার করে, আমরা যে Anyএকটি টাইপ হতে পারে forall a. a -> Anyএবং যেখানে যে forallশব্দ থেকে আসে। আমি বিশ্বাস করি যে জিএইচসি দ্বারা প্রয়োগ করা অস্তিত্বের ধরণগুলি কেবলমাত্র সাধারণ ডেটা টাইপ যা সমস্ত প্রয়োজনীয় টাইপক্লাসের অভিধানও বহন করে (দুঃখিত, আমি এর ব্যাক আপ করার কোনও রেফারেন্স খুঁজে পাইনি)।
ভিটাস

2
@ ভিটাস: জিএইচসি উপস্থিতি টাইপক্লাসের অভিধানগুলিতে আবদ্ধ নয়। আপনি থাকতে পারেন data ApplyBox r = forall a. ApplyBox (a -> r) a; যখন আপনি প্যাটার্নটির সাথে মেলে ApplyBox f x, আপনি পাবেন f :: h -> rএবং x :: hএকটি "লুকানো" সীমাবদ্ধ টাইপের জন্য h। যদি আমি সঠিকভাবে বুঝতে পারি তবে টাইপক্লাস অভিধানের কেসটি এরকম কিছুতে অনুবাদ করা হয়: এরকম কিছুতে অনুবাদ করা data ShowBox = forall a. Show a => ShowBox aহয় data ShowBox' = forall a. ShowBox' (ShowDict' a) a; instance Show ShowBox' where show (ShowBox' dict val) = show' dict val; show' :: ShowDict a -> a -> String
লুইস ক্যাসিলাস

এটি একটি দুর্দান্ত উত্তর আমি কিছু সময় ব্যয় করতে হবে। আমি মনে করি আমি সি # জেনেরিকগুলি প্রদত্ত বিমূর্ততাগুলিতে খুব অভ্যস্ত, তাই আমি তত্ত্বটি বাস্তবে বোঝার পরিবর্তে মঞ্জুর করার জন্য অনেকটা গ্রহণ করছিলাম।
অ্যান্ড্রে শেকकिन

@ সাকুন্ডিম: ওয়েল, "সমস্ত প্রয়োজনীয় টাইপক্লাসের অভিধান" বলতে আপনার কোনও প্রয়োজন না থাকলে কোনও অভিধানের অর্থও দিতে পারে। :) আমার বক্তব্যটি হ'ল জিএইচসি সম্ভবত উচ্চতর স্থান প্রাপ্ত ধরণের (যেমন আপনার প্রস্তাবিত রূপান্তর - PxP (x) ~ r। (PxP (x) → r) → r)) এর মাধ্যমে অস্তিত্বের প্রকারগুলি এনকোড করে না।
ভিটাস

47

লুইস ক্যাসিলাসের উত্তর 2 ধরণের র‌্যাঙ্কটি কী তা বোঝায় সে সম্পর্কে প্রচুর দুর্দান্ত তথ্য দেয় তবে আমি কেবল একটি পয়েন্টে প্রসারিত করব যা তিনি আবরণ করেন নি। বহুমুখী হওয়ার জন্য একটি যুক্তি প্রয়োজন কেবল এটি একাধিক প্রকারের সাথে ব্যবহার করার অনুমতি দেয় না; এটি এই ফাংশনটি তার যুক্তি (গুলি) এর সাথে কী করতে পারে এবং কীভাবে এটির ফলাফল তৈরি করতে পারে তা সীমাবদ্ধ করে। অর্থাৎ এটি কলারকে কম স্বাচ্ছন্দ্য দেয় । আপনি এটি কেন করতে চান? আমি একটি সাধারণ উদাহরণ দিয়ে শুরু করব:

ধরুন আমাদের কাছে একটি ডেটা টাইপ রয়েছে

data Country = BigEnemy | MediumEnemy | PunyEnemy | TradePartner | Ally | BestAlly

এবং আমরা একটি ফাংশন লিখতে চাই

f g = launchMissilesAt $ g [BigEnemy, MediumEnemy, PunyEnemy]

এটি এমন একটি ফাংশন নেয় যা তার দেওয়া তালিকার অন্যতম উপাদান বেছে নেবে এবং IOসেই লক্ষ্যে একটি অ্যাকশন লঞ্চ ক্ষেপণাস্ত্রগুলি ফিরিয়ে দেবে । আমরা fএকটি সহজ ধরণের দিতে পারে :

f :: ([Country] -> Country) -> IO ()

সমস্যাটি হ'ল আমরা দুর্ঘটনাক্রমে চালাতে পারি

f (\_ -> BestAlly)

এবং তারপরে আমরা বড় সমস্যায় পড়ে যাব! প্রদান fএকটি র্যাঙ্ক 1 বহুরুপী টাইপ

f :: ([a] -> a) -> IO ()

মোটেই সহায়তা করে না, কারণ aআমরা কল করার সময় ধরণটি বেছে নিইf এবং আমরা Countryআমাদের দূষিতটিকে \_ -> BestAllyআবার এটিতে বিশেষজ্ঞ এবং ব্যবহার করি । সমাধানটি হ'ল একটি র‌্যাঙ্ক 2 ধরণের ব্যবহার করা:

f :: (forall a . [a] -> a) -> IO ()

এখন আমরা যে ফাংশনটি পাস \_ -> BestAllyকরব তাতে পলিমারফিক হওয়া প্রয়োজন, তাই চেক টাইপ করবেন না! প্রকৃতপক্ষে, যে উপাদানটিকে প্রদত্ত তালিকার মধ্যে নেই তার কোনও ফাংশন ফিরিয়ে দেওয়া হবে না (যদিও এমন কিছু ফাংশন যা অসীম লুপগুলিতে যায় বা ত্রুটি উত্পন্ন করে এবং তাই কখনও ফিরে আসে না) এটি করা হবে না।

উপরেরটি অবশ্যই স্বীকৃত, তবে এই কৌশলটির একটি প্রকরণটি STমনাদকে নিরাপদ করে তোলার মূল বিষয় ।


18

অন্যান্য উত্তরগুলি যেমন উচ্চতর-র‌্যাঙ্কের ধরণের থাকে তেমন বহিরাগত নয়। বিশ্বাস করুন বা না করুন, অনেকগুলি অবজেক্ট-ভিত্তিক ভাষা (জাভা এবং সি # সহ) তাদের বৈশিষ্ট্যযুক্ত করে। (অবশ্যই, সেই সম্প্রদায়ের মধ্যে কেউ তাদের ভয়ঙ্কর-শোনার নাম "উচ্চ-স্তরের প্রকারগুলি" দ্বারা চেনে না))

আমি যে উদাহরণটি দিতে যাচ্ছি তা হ'ল ভিজিটর প্যাটার্নের একটি পাঠ্যপুস্তক বাস্তবায়ন, যা আমি আমার প্রতিদিনের কাজে সব সময় ব্যবহার করি। এই উত্তরটি দর্শকের প্যাটার্নের পরিচিতি হিসাবে নয়; যে জ্ঞান অন্য কোথাও সহজেই উপলব্ধ

এই চর্চিত কাল্পনিক এইচআর অ্যাপ্লিকেশনটিতে আমরা এমন কর্মচারীদের উপর পরিচালনা করতে চাই যা পুরো সময়ের স্থায়ী কর্মী বা অস্থায়ী ঠিকাদার হতে পারে। আমার দর্শনার্থী প্যাটার্নের পছন্দসই বৈকল্পিক (এবং প্রকৃতপক্ষে এটি প্রাসঙ্গিক RankNTypes) ভিজিটরের ফেরতের ধরণের প্যারামিটারাইজেস করে।

interface IEmployeeVisitor<T>
{
    T Visit(PermanentEmployee e);
    T Visit(Contractor c);
}

class XmlVisitor : IEmployeeVisitor<string> { /* ... */ }
class PaymentCalculator : IEmployeeVisitor<int> { /* ... */ }

মুল বক্তব্যটি হ'ল বিভিন্ন রিটার্নের ধরণের সংখ্যক দর্শক সমস্ত একই ডেটাতে পরিচালনা করতে পারে operate এর অর্থ IEmployeeকী Tহওয়া উচিত তা সম্পর্কে কোনও মতামত প্রকাশ করতে হবে না।

interface IEmployee
{
    T Accept<T>(IEmployeeVisitor<T> v);
}
class PermanentEmployee : IEmployee
{
    // ...
    public T Accept<T>(IEmployeeVisitor<T> v)
    {
        return v.Visit(this);
    }
}
class Contractor : IEmployee
{
    // ...
    public T Accept<T>(IEmployeeVisitor<T> v)
    {
        return v.Visit(this);
    }
}

আমি ধরণের প্রতি আপনার দৃষ্টি আকর্ষণ করতে ইচ্ছুক। পর্যবেক্ষণ করুন যে IEmployeeVisitorসর্বজনীনভাবে তার রিটার্নের প্রকারটি IEmployeeপরিমাণযুক্ত করে , যেখানে এটি তার Acceptপদ্ধতির অভ্যন্তরে পরিমাণযুক্ত করে - এটি উচ্চতর পদে বলে। সি # থেকে হাস্কেলের কাছে কঙ্কুলভাবে অনুবাদ করা:

data IEmployeeVisitor r = IEmployeeVisitor {
    visitPermanent :: PermanentEmployee -> r,
    visitContractor :: Contractor -> r
}

newtype IEmployee = IEmployee {
    accept :: forall r. IEmployeeVisitor r -> r
}

তাই সেখানে যদি আপনি এটি আছে। আপনি জেনেরিক পদ্ধতিযুক্ত প্রকারগুলি লিখলে উচ্চ-স্তরের প্রকারগুলি সি # তে প্রদর্শিত হয়।


1
আমি আরও জানতে চাই যে উচ্চমানের ধরণের জন্য অন্য কেউ সি # / জাভা / ব্লাবের সমর্থন সম্পর্কে লিখেছেন কিনা। আপনি যদি প্রিয় পাঠক, এই জাতীয় কোনও সংস্থান সম্পর্কে জানেন তবে দয়া করে তাদের আমার পাঠান!
বেঞ্জামিন হজসন


-2

অবজেক্ট ওরিয়েন্টেড ভাষাগুলির সাথে পরিচিতদের জন্য, একটি উচ্চ-স্তরের ফাংশন কেবল একটি জেনেরিক ফাংশন যা তার যুক্তি হিসাবে অন্য জেনেরিক ফাংশন হিসাবে প্রত্যাশা করে।

যেমন টাইপস্ক্রিপ্টে আপনি লিখতে পারেন:

type WithId<T> = T & { id: number }
type Identifier = <T>(obj: T) => WithId<T>
type Identify = <TObj>(obj: TObj, f: Identifier) => WithId<TObj>

জেনেরিক ফাংশন প্রকারটি কীভাবে জেনেরিক ফাংশনটির Identifyদাবি করে তা দেখুন Identifier? এটি Identifyএকটি উচ্চ-র‌্যাঙ্ক ফাংশন করে।


এটি Sepp2k এর উত্তরে কী যুক্ত করে?
ডিফিউয়ার

বা বেঞ্জামিন হজসন এর জন্য?
ডিফিউয়ার

1
আমি মনে করি আপনি হজসনের বক্তব্য মিস করেছেন। Acceptর‌্যাঙ্ক -১ পলিমর্ফিক টাইপ রয়েছে তবে এটি একটি পদ্ধতি IEmployeeযা নিজেই র‌্যাঙ্ক -২। যদি কেউ আমাকে একটি দেয় তবে IEmployeeআমি এটিকে খুলতে এবং Acceptযেকোন প্রকারে এর পদ্ধতিটি ব্যবহার করতে পারি ।
ডিফিউয়ার

1
আপনার পরিচিতিটি Visiteeক্লাসের মাধ্যমে আপনার উদাহরণটিও র‌্যাঙ্ক -২ । একটি ফাংশন f :: Visitee e => T eহ'ল (একবার ক্লাস স্টাফগুলি ডিজাইন করা হয়) মূলত f :: (forall r. e -> Visitor e r -> r) -> T e। হাস্কেল 2010 আপনাকে এর মতো ক্লাস ব্যবহার করে সীমিত র‌্যাঙ্ক -2 পলিমারফিজম দিয়ে দূরে যেতে দেয়।
dfeuer

1
আপনি forallআমার উদাহরণে ভাসা করতে পারবেন না । আমার হাতে কোনও রেফারেন্স নেই, তবে আপনি "আপনার টাইপ ক্লাসগুলি স্ক্র্যাপ করুন" এ ভালভাবে কিছু পেতে পারেন । উচ্চ-র‌্যাঙ্কের বহুবৈচিত্র্য প্রকৃতপক্ষে টাইপ-চেকিংয়ের সমস্যাগুলি পরিচয় করিয়ে দিতে পারে তবে শ্রেণি ব্যবস্থায় অন্তর্নিহিত সীমিত সাজাই ঠিক আছে।
dfeuer
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.