Rust में Traits और Haskell में Typeclasses: अमूर्तता की लड़ाई

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

परिचय: Rust और Haskell की तुलना क्यों करें?

\n\n

यदि आपने कभी Stack Overflow पर "Rust में traits और Haskell में typeclasses के बीच क्या अंतर है?" प्रश्न का उत्तर खोजा है, तो आप जानते हैं: यह विषय बहुत गर्म है। हज़ारों व्यूज़, दर्जनों वोट — डेवलपर समुदाय वास्तव में यह समझना चाहता है कि ये दोनों तंत्र कैसे भिन्न हैं।

\n\n

पहली नज़र में, वे भाइयों की तरह दिखते हैं: Rust में traits और Haskell में typeclasses दोनों ही विभिन्न प्रकारों के लिए सामान्य व्यवहार को परिभाषित करने की अनुमति देते हैं। लेकिन यदि आप गहराई से देखें, तो पता चलता है कि उनका दर्शन, कार्यान्वयन और व्यावहारिक अनुप्रयोग अलग-अलग ब्रह्मांड हैं।

\n\n

इस लेख में, हम Rust में वास्तविक कोड उदाहरणों (तुलना के लिए Haskell के कुछ अंशों के साथ) पर मुख्य अंतरों का विश्लेषण करेंगे, और अंत में आपको स्पष्ट समझ मिलेगी: traits का उपयोग कब करें, और typeclass-जैसे दृष्टिकोण के बारे में कब सोचना बेहतर है।

\n\n

संक्षिप्त अवलोकन: Rust में traits क्या हैं?

\n\n

Traits Rust में उन विधियों के एक सेट की घोषणा करने का एक तरीका है जिन्हें किसी विशिष्ट प्रकार के लिए लागू किया जाना चाहिए। यह सामान्यीकृत प्रोग्रामिंग (generics) और Rust में पॉलीमॉर्फिज्म का आधार है।

\n\n

एक सरल उदाहरण: कल्पना करें कि हम चाहते हैं कि विभिन्न प्रकार "नमस्ते" कह सकें।

\n\n
trait Greeter {\n    fn greet(&self) -> String;\n}\n\nstruct Person {\n    name: String,\n}\n\nimpl Greeter for Person {\n    fn greet(&self) -> String {\n        format!("नमस्ते, मेरा नाम {} है!", self.name)\n    }\n}\n\nstruct Robot {\n    model: String,\n}\n\nimpl Greeter for Robot {\n    fn greet(&self) -> String {\n        format!("बीप-बूप, मॉडल: {}", self.model)\n    }\n}\n\nfn say_hello(item: &impl Greeter) {\n    println!("{}", item.greet());\n}\n\nfn main() {\n    let person = Person { name: "अन्ना".into() };\n    let robot = Robot { model: "R2-D2".into() };\n    say_hello(&person);\n    say_hello(&robot);\n}
\n\n

यहाँ Greeter एक trait है। Person और Robot प्रकार इसे अपने-अपने तरीके से लागू करते हैं। फ़ंक्शन say_hello किसी भी प्रकार को स्वीकार करता है जो Greeter को लागू करता है। यही traits के माध्यम से पॉलीमॉर्फिज्म है।

\n\n

संक्षिप्त अवलोकन: Haskell में typeclasses क्या हैं?

\n\n

Typeclass Haskell में एक इंटरफ़ेस है जो फ़ंक्शन के एक सेट को परिभाषित करता है जिसे विभिन्न प्रकारों के लिए लागू किया जा सकता है। परिचित लगता है, है ना?

\n\n

Haskell में समान उदाहरण इस प्रकार दिखेगा:

\n\n
class Greeter a where\n    greet :: a -> String\n\ndata Person = Person { name :: String }\ndata Robot = Robot { model :: String }\n\ninstance Greeter Person where\n    greet (Person n) = "नमस्ते, मेरा नाम " ++ n ++ "!"\n\ninstance Greeter Robot where\n    greet (Robot m) = "बीप-बूप, मॉडल: " ++ m\n\nsayHello :: Greeter a => a -> IO ()\nsayHello item = putStrLn (greet item)\n\nmain = do\n    sayHello (Person "अन्ना")\n    sayHello (Robot "R2-D2")
\n\n

सिंटैक्स अलग है, लेकिन तर्क वही है। और फिर भी Rust में traits और Haskell में typeclasses के बीच अंतर यहीं से शुरू होते हैं।

\n\n

मुख्य अंतर #1: मोनोमॉर्फ़ाइज़ेशन बनाम बॉक्स (Box)

\n\n

सबसे मौलिक traits और typeclasses के बीच अंतर इस बात में निहित है कि कंपाइलर सामान्यीकृत कोड को कैसे संसाधित करता है।

\n\n

Rust: मोनोमॉर्फ़ाइज़ेशन

\n\n

जब आप fn say_hello(item: &impl Greeter) लिखते हैं, तो Rust कंपाइलर प्रत्येक विशिष्ट प्रकार के लिए फ़ंक्शन की एक अलग प्रतिलिपि बनाता है। इसे मोनोमॉर्फ़ाइज़ेशन कहा जाता है। परिणाम: शून्य-लागत अमूर्तता (zero-cost abstraction) — आप उस चीज़ के लिए भुगतान नहीं करते जिसका आप उपयोग नहीं करते। लेकिन कोड का आकार बढ़ सकता है।

\n\n

Haskell: बॉक्स (डिफ़ॉल्ट रूप से)

\n\n

Haskell में, typeclass को आमतौर पर विधि शब्दकोशों (vtable) के माध्यम से लागू किया जाता है। कंपाइलर एक अंतर्निहित पैरामीटर पास करता है — फ़ंक्शन पॉइंटर्स वाली एक तालिका। इसे बॉक्सिंग कहा जाता है। आप को

ब्लॉग

पुस्तक अनुशंसाएँ