हास्केल प्रकार बनाम डेटा कंस्ट्रक्टर


124

मैं learnyouahaskell.com से हास्केल सीख रहा हूं । मुझे टाइप कंस्ट्रक्टर्स और डेटा कंस्ट्रक्टर्स को समझने में परेशानी हो रही है। उदाहरण के लिए, मैं वास्तव में इस बीच का अंतर नहीं समझता:

data Car = Car { company :: String  
               , model :: String  
               , year :: Int  
               } deriving (Show) 

और इस:

data Car a b c = Car { company :: a  
                     , model :: b  
                     , year :: c   
                     } deriving (Show)  

मैं समझता हूं कि पहला केवल एक कंस्ट्रक्टर ( Car) से निर्मित डेटा का उपयोग कर रहा है Car। मैं वास्तव में दूसरे को नहीं समझता।

इसके अलावा, इस प्रकार परिभाषित डेटा प्रकार कैसे हैं:

data Color = Blue | Green | Red

इस सब में फिट?

मैं क्या समझ से, तीसरा उदाहरण ( Color:) एक प्रकार है जो तीन राज्यों में हो सकता है Blue, Greenया Red। लेकिन यह इस बात से टकराता है कि मैं पहले दो उदाहरणों को कैसे समझता हूं: क्या यह है कि प्रकार Carकेवल एक राज्य में हो सकता है Car, जो निर्माण के लिए विभिन्न मापदंडों को ले सकता है? यदि हां, तो दूसरा उदाहरण कैसे फिट होता है?

अनिवार्य रूप से, मैं एक स्पष्टीकरण की तलाश कर रहा हूं जो उपरोक्त तीन कोड उदाहरणों / निर्माणों को एकजुट करता है।


18
आपकी कार का उदाहरण थोड़ा भ्रमित करने वाला हो सकता है क्योंकि Carएक प्रकार का कंस्ट्रक्टर (बाईं ओर =) और एक डेटा कंस्ट्रक्टर (दाईं ओर) दोनों है। पहले उदाहरण में, Carटाइप कंस्ट्रक्टर कोई तर्क नहीं लेता है, दूसरे उदाहरण में इसे तीन लगते हैं। दोनों उदाहरणों में, Carडेटा कंस्ट्रक्टर तीन तर्क लेता है (लेकिन उन तर्कों के प्रकार एक मामले में तय किए गए और दूसरे पैरामीटर में हैं)।
साइमन शाइन

पहला Car :: String -> String -> Int -> Carडेटा प्रकार का निर्माण करने के लिए बस एक डेटा कंस्ट्रक्टर ( ) का उपयोग कर रहा है Car। दूसरे Car :: a -> b -> c -> Car a b cप्रकार के डेटा के निर्माण के लिए बस एक डेटा कंस्ट्रक्टर ( ) का उपयोग किया जाता है Car a b c
विल नेस

जवाबों:


228

एक dataघोषणा में, एक प्रकार का निर्माणकर्ता बराबरी के चिह्न के बाईं ओर की चीज है। डेटा निर्माता (रों) दाहिने हाथ की ओर चीजों के बराबर के चिह्न हैं। आप टाइप कंस्ट्रक्टर्स का उपयोग करते हैं जहां एक प्रकार की उम्मीद की जाती है, और आप उन डेटा कंस्ट्रक्टर्स का उपयोग करते हैं जहां एक मूल्य अपेक्षित होता है।

डेटा कंस्ट्रक्टर

चीजों को सरल बनाने के लिए, हम एक प्रकार के उदाहरण से शुरू कर सकते हैं जो एक रंग का प्रतिनिधित्व करता है।

data Colour = Red | Green | Blue

यहां, हमारे पास तीन डेटा कंस्ट्रक्टर हैं। Colourएक प्रकार है, और Greenएक निर्माता है जिसमें प्रकार का मान होता है Colour। इसी तरह, Redऔर Blueदोनों निर्माता हैं जो प्रकार के मूल्यों का निर्माण करते हैं Colour। हम कल्पना कर सकते हैं हालांकि यह spicing!

data Colour = RGB Int Int Int

हमारे पास अभी भी केवल प्रकार है Colour, लेकिन RGBएक मूल्य नहीं है - यह एक फ़ंक्शन है जिसमें तीन इनट्स ले रहे हैं और एक मान लौटा रहे हैं ! RGBप्रकार है

RGB :: Int -> Int -> Int -> Colour

RGBएक डेटा कंस्ट्रक्टर है जो एक फ़ंक्शन है जो कुछ मानों को अपने तर्कों के रूप में लेता है, और फिर एक नए मूल्य का निर्माण करने के लिए उन का उपयोग करता है। यदि आपने कोई ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग की है, तो आपको इसे पहचानना चाहिए। OOP में, निर्माता कुछ मानों को तर्क के रूप में लेते हैं और एक नया मान लौटाते हैं!

इस मामले में, यदि हम RGBतीन मूल्यों पर लागू होते हैं, तो हमें एक रंग मूल्य मिलता है!

Prelude> RGB 12 92 27
#0c5c1b

हमने डेटा कंस्ट्रक्टर को लागू करके प्रकार का एक मानColour बनाया है। डेटा कंस्ट्रक्टर में या तो वैरिएबल जैसा कोई मान होता है, या अन्य मानों को इसके तर्क के रूप में लेता है और एक नया मान बनाता है । यदि आपने पिछली प्रोग्रामिंग की है, तो यह अवधारणा आपके लिए बहुत अजीब नहीं होनी चाहिए।

विराम

यदि आप Strings स्टोर करने के लिए एक बाइनरी ट्री का निर्माण करना चाहते हैं , तो आप कुछ ऐसा करने की कल्पना कर सकते हैं

data SBTree = Leaf String
            | Branch String SBTree SBTree

हम यहां जो देख रहे हैं वह एक प्रकार SBTreeहै जिसमें दो डेटा निर्माता हैं। दूसरे शब्दों में, वहाँ दो कार्य (अर्थात् हैं Leafऔर Branch) है कि के मूल्यों का निर्माण करेगी SBTreeप्रकार। यदि आप इस बात से परिचित नहीं हैं कि द्विआधारी पेड़ कैसे काम करते हैं, तो बस वहां लटके रहें। आपको वास्तव में यह जानने की आवश्यकता नहीं है कि बाइनरी पेड़ कैसे काम करते हैं, केवल यह कि यह Stringकिसी तरह से स्टोर करता है ।

हम यह भी देखते हैं कि दोनों डेटा निर्माता एक Stringतर्क लेते हैं - यह वह स्ट्रिंग है जिसे वे पेड़ में स्टोर करने जा रहे हैं।

परंतु! क्या होगा अगर हम भी स्टोर करने में सक्षम होना Boolचाहते हैं, तो हमें एक नया बाइनरी ट्री बनाना होगा। यह कुछ इस तरह दिख सकता है:

data BBTree = Leaf Bool
            | Branch Bool BBTree BBTree

कंस्ट्रक्टर टाइप करें

दोनों SBTreeऔर BBTreeप्रकार निर्माता ये हैं। लेकिन एक भयावह समस्या है। क्या आप देखते हैं कि वे कितने समान हैं? यह एक संकेत है कि आप वास्तव में एक पैरामीटर कहीं चाहते हैं।

तो हम यह कर सकते हैं:

data BTree a = Leaf a
             | Branch a (BTree a) (BTree a)

अब हम टाइप कंस्ट्रक्टर के पैरामीटर के रूप में एक वेरिएबल a टाइप करते हैं। इस घोषणा में, BTreeएक कार्य बन गया है। यह अपने तर्क के रूप में एक प्रकार लेता है और यह एक नया प्रकार लौटाता है ।

एक ठोस प्रकार (उदाहरण शामिल हैं Int, [Char]और Maybe Bool) के बीच अंतर पर विचार करना यहां महत्वपूर्ण है जो एक प्रकार है जिसे आपके कार्यक्रम में एक मूल्य को सौंपा जा सकता है, और एक प्रकार का निर्माण कार्य जिसे आप करने में सक्षम होने के लिए एक प्रकार खिलाने की आवश्यकता है एक मूल्य के लिए सौंपा। एक मान कभी भी "सूची" प्रकार का नहीं हो सकता है, क्योंकि इसे "किसी चीज़ की सूची" होने की आवश्यकता है । एक ही भावना में, एक मूल्य, प्रकार "द्विआधारी पेड़" की कभी नहीं हो सकता है क्योंकि यह एक "बाइनरी पेड़ भंडारण होने की जरूरत है कुछ "।

अगर हम इसमें पास होते हैं, तो Boolएक तर्क के रूप में BTree, यह उस प्रकार को लौटाता है BTree Bool, जो एक द्विआधारी वृक्ष है जो Boolएस स्टोर करता है । प्रकार की प्रत्येक घटना को प्रकार के aसाथ बदलें Bool, और आप स्वयं देख सकते हैं कि यह कैसे सच है।

यदि आप चाहते हैं, तो आप प्रकार केBTree साथ एक फ़ंक्शन के रूप में देख सकते हैं

BTree :: * -> *

प्रकार कुछ प्रकार के होते हैं - *एक ठोस प्रकार को इंगित करता है, इसलिए हम कहते हैं कि BTreeएक ठोस प्रकार से एक ठोस प्रकार है।

समेट रहा हु

यहां एक पल वापस कदम रखें और समानता का ध्यान रखें।

  • एक डेटा कंस्ट्रक्टर एक "फ़ंक्शन" है जो 0 या अधिक मान लेता है और आपको एक नया मान देता है।

  • एक प्रकार का निर्माता एक "फ़ंक्शन" है जो 0 या अधिक प्रकार लेता है और आपको एक नया प्रकार वापस देता है।

यदि हम अपने मूल्यों में थोड़ी भिन्नता चाहते हैं तो मापदंडों के साथ डेटा निर्माता शांत होते हैं - हम उन भिन्नताओं को मापदंडों में डालते हैं और उस व्यक्ति को मान देते हैं जो मूल्य तय करते हैं कि वे क्या तर्क देने वाले हैं। अगर हम अपने प्रकारों में मामूली बदलाव चाहते हैं! हम उन विविधताओं को मापदंडों के रूप में रखते हैं और उस व्यक्ति को टाइप करने देते हैं जो यह तय करता है कि वे कौन से तर्क देने वाले हैं।

एक मामले का अध्ययन

घर के खिंचाव के रूप में, हम इस Maybe aप्रकार पर विचार कर सकते हैं । इसकी परिभाषा है

data Maybe a = Nothing
             | Just a

यहाँ, Maybeएक प्रकार का कंस्ट्रक्टर है जो एक ठोस प्रकार देता है। Justएक डेटा कंस्ट्रक्टर है जो एक मूल्य लौटाता है। Nothingएक डेटा कंस्ट्रक्टर है जिसमें एक मान होता है। यदि हम किस प्रकार को Justदेखते हैं, तो हम देखते हैं

Just :: a -> Maybe a

दूसरे शब्दों में, Justप्रकार का मान लेता है aऔर प्रकार का मान लौटाता है Maybe a। अगर हम उस तरह के को Maybeदेखते हैं, तो हम देखते हैं

Maybe :: * -> *

दूसरे शब्दों में, Maybeएक ठोस प्रकार लेता है और एक ठोस प्रकार देता है।

एक बार फिर! एक ठोस प्रकार और एक प्रकार के निर्माण कार्य के बीच का अंतर। Maybeयदि आप निष्पादित करने का प्रयास करते हैं, तो आप s की सूची नहीं बना सकते हैं

[] :: [Maybe]

आपको एक त्रुटि मिलेगी। आप हालांकि Maybe Int, या की एक सूची बना सकते हैं Maybe a। ऐसा इसलिए Maybeहै क्योंकि एक प्रकार का निर्माण कार्य है, लेकिन एक सूची में एक ठोस प्रकार के मूल्यों को शामिल करने की आवश्यकता है। Maybe Intऔर Maybe aठोस प्रकार हैं (या यदि आप चाहते हैं, तो निर्माण कार्यों को टाइप करने के लिए कॉल करें जो कंक्रीट प्रकार लौटाते हैं।)


2
आपके पहले उदाहरण में, RED GREEN और BLUE दोनों ऐसे निर्माता हैं जो कोई तर्क नहीं देते हैं।
ओलीबी

3
यह दावा कि data Colour = Red | Green | Blue"हमारे पास कोई भी निर्माणकर्ता नहीं है" सादा गलत है। टाइप कंस्ट्रक्टर्स और डेटा कंस्ट्रक्टर्स को तर्कों को लेने की आवश्यकता नहीं है, उदाहरण के लिए haskell.org/haskellwiki/Constructor देखें जो बताते हैं कि data Tree a = Tip | Node a (Tree a) (Tree a), "दो डेटा कंस्ट्रक्टर, टिप और नोड" हैं।
Frerich Raabe

1
@CMCDragonkai आप बिल्कुल सही हैं! प्रकार "प्रकार के होते हैं।" प्रकारों और मूल्यों की अवधारणाओं में शामिल होने के लिए एक सामान्य दृष्टिकोण को आश्रित टाइपिंग कहा जाता हैइदरीस एक हास्केल से प्रेरित भरोसेमंद भाषा है। सही GHC एक्सटेंशन के साथ, आप हास्केल में आश्रित टाइपिंग के लिए कुछ हद तक पास हो सकते हैं। (कुछ लोग मजाक में कह रहे हैं कि "हास्केल शोध यह पता लगाने के बारे में है कि हम निर्भर प्रकारों के बिना कितने प्रकार के करीब पहुंच सकते हैं।")
kqr

1
@CMCDragonkai मानक हास्केल में खाली डेटा घोषणा होना वास्तव में संभव नहीं है। लेकिन एक GHC एक्सटेंशन ( -XEmptyDataDecls) है जो आपको ऐसा करने देता है। चूंकि, जैसा कि आप कहते हैं, उस प्रकार के साथ कोई मूल्य नहीं हैं, f :: Int -> Zउदाहरण के लिए एक फ़ंक्शन कभी वापस नहीं आ सकता है (क्योंकि यह क्या लौटाएगा?) हालांकि वे तब भी आपके लिए उपयोगी हो सकते हैं जब आप प्रकार चाहते हैं लेकिन वास्तव में मूल्यों की परवाह नहीं करते हैं
kqr

1
वास्तव में यह संभव नहीं है? मैंने जीएचसी में सिर्फ कोशिश की, और इसे बिना किसी त्रुटि के चलाया। मुझे किसी भी जीएचसी एक्सटेंशन को लोड नहीं करना था, बस वेनिला जीएचसी। मैं तब लिख सकता था :k Zऔर इसने मुझे एक स्टार दिया।
CMCDragonkai

42

हास्केल में बीजीय डेटा प्रकार हैं , जो बहुत कम अन्य भाषाओं में हैं। शायद यही आपको भ्रमित कर रहा है।

अन्य भाषाओं में, आप आमतौर पर एक "रिकॉर्ड", "संरचना" या समान बना सकते हैं, जिसमें नामित क्षेत्रों का एक गुच्छा होता है जो विभिन्न प्रकार के डेटा रखता है। आप कभी-कभी एक "गणना" भी बना सकते हैं, जिसमें निश्चित संभावित मानों (जैसे, आपका Red, Greenऔर Blue) का एक (छोटा) सेट होता है ।

हास्केल में, आप एक ही समय में इन दोनों को जोड़ सकते हैं । अजीब है, लेकिन सच है!

इसे "बीजगणितीय" क्यों कहा जाता है? खैर, नर्ड "योग प्रकार" और "उत्पाद प्रकार" के बारे में बात करते हैं। उदाहरण के लिए:

data Eg1 = One Int | Two String

एक Eg1मूल्य मूल रूप से है या तो एक पूर्णांक या एक स्ट्रिंग। तो सभी संभावित Eg1मूल्यों का सेट सभी संभव पूर्णांक मानों और सभी संभव स्ट्रिंग मानों के सेट का "योग" है। इस प्रकार, nerds Eg1एक "योग प्रकार" के रूप में संदर्भित होता है । दूसरी ओर:

data Eg2 = Pair Int String

प्रत्येक Eg2मान में पूर्णांक और एक स्ट्रिंग दोनों होते हैं । तो सभी संभावित Eg2मूल्यों का सेट सभी पूर्णांकों के सेट और सभी तारों के सेट का कार्टेशियन उत्पाद है। दो सेट एक साथ "गुणा" होते हैं, इसलिए यह एक "उत्पाद प्रकार" है।

हास्केल के बीजीय प्रकार उत्पाद प्रकार के योग हैं । आप एक निर्माता को एक उत्पाद प्रकार बनाने के लिए कई फ़ील्ड देते हैं, और आपके पास एक उत्पाद (राशि) बनाने के लिए कई निर्माता होते हैं।

उदाहरण के लिए कि यह उपयोगी क्यों हो सकता है, मान लें कि आपके पास XML या JSON के रूप में डेटा को आउटपुट करने वाला कुछ है, और यह कॉन्फ़िगरेशन रिकॉर्ड लेता है - लेकिन जाहिर है, XML और JSON के लिए कॉन्फ़िगरेशन सेटिंग्स पूरी तरह से अलग हैं। तो आप ऐसा कुछ कर सकते हैं:

data Config = XML_Config {...} | JSON_Config {...}

(वहाँ कुछ उपयुक्त क्षेत्रों के साथ, जाहिर है।) आप सामान्य प्रोग्रामिंग भाषाओं में इस तरह से सामान नहीं कर सकते हैं, यही कारण है कि ज्यादातर लोगों को इसका उपयोग नहीं किया जाता है।


4
महान! सिर्फ एक ही बात, "वे कर सकते हैं ... लगभग किसी भी भाषा में निर्माण किया जा सकता है", विकिपीडिया कहते हैं । :) उदाहरण के लिए C / ++, यह unionएक टैग अनुशासन के साथ है। :)
विल नेस

5
हाँ, लेकिन हर बार जब मैं उल्लेख करता हूं union, तो लोग मेरी तरह देखते हैं "कौन नरक कभी भी इसका उपयोग करता है ??" ;-)
मैथमैटिकलऑर्चिड

1
मैंने unionअपने सी करियर में बहुत इस्तेमाल किया है। कृपया इसे अनावश्यक न बनाएं क्योंकि ऐसा नहीं है।

26

सबसे सरल मामले से शुरू करें:

data Color = Blue | Green | Red

यह एक "टाइप कंस्ट्रक्टर" को परिभाषित करता है Colorजो कोई तर्क नहीं लेता है - और इसमें तीन "डेटा कंस्ट्रक्टर" हैं Blue, Greenऔर Red। कोई भी डेटा कंस्ट्रक्टर कोई भी तर्क नहीं देता है। इस का अर्थ है कि प्रकार के तीन हैं कि Color: Blue, Greenऔर Red

एक डेटा कंस्ट्रक्टर का उपयोग तब किया जाता है जब आपको किसी प्रकार का मान बनाने की आवश्यकता होती है। पसंद:

myFavoriteColor :: Color
myFavoriteColor = Green

डेटा कंस्ट्रक्टर myFavoriteColorका उपयोग करके एक मान बनाता है Green- और myFavoriteColorप्रकार का होगा Colorक्योंकि डेटा कंस्ट्रक्टर द्वारा उत्पादित मानों का प्रकार है।

एक प्रकार के निर्माता का उपयोग तब किया जाता है जब आपको किसी प्रकार का एक प्रकार बनाने की आवश्यकता होती है । यह आमतौर पर हस्ताक्षर लिखते समय मामला होता है:

isFavoriteColor :: Color -> Bool

इस मामले में, आप Colorटाइप कंस्ट्रक्टर कह रहे हैं (जिसमें कोई तर्क नहीं है)।

अभी तक मेरे साथ है?

अब, कल्पना कीजिए कि आप न केवल लाल / हरे / नीले मूल्यों को बनाना चाहते थे बल्कि आप एक "तीव्रता" भी निर्दिष्ट करना चाहते थे। जैसे, 0 और 256 के बीच का मान। आप डेटा कंस्ट्रक्टर्स में से प्रत्येक में एक तर्क जोड़कर ऐसा कर सकते हैं, इसलिए आप इसके साथ समाप्त होते हैं:

data Color = Blue Int | Green Int | Red Int

अब, तीन डेटा निर्माता में से प्रत्येक प्रकार का तर्क लेता है Int। प्रकार कंस्ट्रक्टर ( Color) अभी भी कोई तर्क नहीं लेता है। इसलिए, मेरा पसंदीदा रंग गहरा हरा है, मैं लिख सकता हूं

    myFavoriteColor :: Color
    myFavoriteColor = Green 50

और फिर से, यह Greenडेटा कंस्ट्रक्टर को कॉल करता है और मुझे एक प्रकार का मूल्य मिलता है Color

सोचिए अगर आप यह नहीं बताना चाहते कि लोग किसी रंग की तीव्रता को कैसे व्यक्त करते हैं। कुछ हम चाहते हैं कि जैसे एक संख्यात्मक मूल्य चाहते हैं। अन्य लोग बस एक बूलियन के साथ ठीक हो सकते हैं जो "उज्ज्वल" या "इतना उज्ज्वल नहीं" दर्शाता है। इसका समाधान Intडेटा कंस्ट्रक्टर्स में हार्डकोड नहीं है , बल्कि एक प्रकार के चर का उपयोग करना है:

data Color a = Blue a | Green a | Red a

अब, हमारा टाइप कंस्ट्रक्टर एक तर्क लेता है (एक अन्य प्रकार जिसे हम बस कहते हैं a!) और सभी डेटा कंस्ट्रक्टर उस प्रकार के एक (एक मान!) लेंगे a। तो आप कर सकते थे

myFavoriteColor :: Color Bool
myFavoriteColor = Green False

या

myFavoriteColor :: Color Int
myFavoriteColor = Green 50

ध्यान दें कि हम कैसे कहते हैं Color "प्रभावी" प्रकार को प्राप्त करने के लिए टाइप कंस्ट्रक्टर को एक तर्क (दूसरे प्रकार) के साथ कहते हैं जो डेटा कंस्ट्रक्टर्स द्वारा वापस कर दिया जाएगा। यह एक प्रकार की अवधारणा को छूता है जिसे आप एक कप कॉफी या दो के बारे में पढ़ना चाहते हैं।

अब हमने पता लगाया कि डेटा कंस्ट्रक्टर और टाइप कंस्ट्रक्टर क्या हैं, और डेटा कंस्ट्रक्टर अन्य मान कैसे ले सकते हैं क्योंकि तर्क और टाइप कंस्ट्रक्टर अन्य प्रकार के तर्क ले सकते हैं। HTH।


मुझे यकीन नहीं है कि मैं एक अशक्त डेटा निर्माता की आपकी धारणा के साथ दोस्त हूं। मुझे पता है कि हास्केल में स्थिरांक के बारे में बात करना एक सामान्य तरीका है, लेकिन क्या यह काफी बार गलत साबित हुआ है?
kqr

@kqr: एक डेटा कंस्ट्रक्टर अशक्त हो सकता है, लेकिन तब यह एक फ़ंक्शन नहीं है। एक फ़ंक्शन एक ऐसी चीज़ है जो एक तर्क लेती है और ->हस्ताक्षर में एक मूल्य, यानी कुछ के साथ उपज देती है ।
Frerich Raabe

क्या एक मूल्य कई प्रकार का हो सकता है? या हर मूल्य केवल 1 प्रकार से जुड़ा होता है और यह है?
CMCDragonkai

1
@jrg कुछ ओवरलैप है, लेकिन यह विशेष रूप से टाइप कंस्ट्रक्टर्स के कारण नहीं है, बल्कि टाइप वैरिएबल के कारण है, जैसे कि aअंदर data Color a = Red aaएक मनमाना प्रकार के लिए एक प्लेसहोल्डर है। हालांकि, जैसे एक प्रकार का कार्य आप सादे कार्यों में एक ही हो सकता है (a, b) -> a(प्रकार के दो मूल्यों की एक टपल लेता है aऔर b) और पहली मूल्य अर्जित करता है। यह एक "सामान्य" फ़ंक्शन है जिसमें यह टपल तत्वों के प्रकार को निर्धारित नहीं करता है - यह केवल यह निर्दिष्ट करता है कि फ़ंक्शन पहले टपल तत्व के समान प्रकार का मान देता है।
फ्रैरिच राबे

1
+1 Now, our type constructor takes one argument (another type which we just call a!) and all of the data constructors will take one argument (a value!) of that type a.यह बहुत मददगार है।
जोनास

5

जैसा कि दूसरों ने बताया, बहुरूपता यहाँ भयानक नहीं है। आइए एक और उदाहरण देखें जिससे आप शायद पहले से परिचित हैं:

Maybe a = Just a | Nothing

इस प्रकार के दो डेटा निर्माता हैं। Nothingकुछ हद तक उबाऊ है, इसमें कोई उपयोगी डेटा नहीं है। दूसरी ओर Justएक मान होता है a- जो भी प्रकार aहो सकता है। आइए एक फ़ंक्शन लिखें जो इस प्रकार का उपयोग करता है, उदाहरण के लिए एक Intसूची का प्रमुख हो रहा है , अगर कोई है (मुझे आशा है कि आप सहमत हैं कि यह एक त्रुटि फेंकने से अधिक उपयोगी है):

maybeHead :: [Int] -> Maybe Int
maybeHead [] = Nothing
maybeHead (x:_) = Just x

> maybeHead [1,2,3]    -- Just 1
> maybeHead []         -- None

तो इस मामले aमें एक है Int, लेकिन यह किसी अन्य प्रकार के लिए भी काम करेगा। वास्तव में आप हमारे कार्य को हर प्रकार की सूची के लिए काम कर सकते हैं (यहां तक ​​कि कार्यान्वयन को बदले बिना):

maybeHead :: [t] -> Maybe t
maybeHead [] = Nothing
maybeHead (x:_) = Just x

दूसरी ओर आप ऐसे कार्य लिख सकते हैं जो केवल एक निश्चित प्रकार के Maybeउदाहरण को स्वीकार करते हैं

doubleMaybe :: Maybe Int -> Maybe Int
doubleMaybe Just x = Just (2*x)
doubleMaybe Nothing= Nothing

इतनी लंबी कहानी छोटी, बहुरूपता के साथ आप विभिन्न प्रकार के मूल्यों के साथ काम करने के लिए अपने स्वयं के प्रकार को लचीलापन देते हैं।

आपके उदाहरण में, आप कुछ बिंदु पर निर्णय ले सकते हैं Stringजो कंपनी की पहचान करने के लिए पर्याप्त नहीं है, लेकिन इसके लिए अपना स्वयं का प्रकार Company(जो कि देश, पता, बैक अकाउंट आदि जैसे अतिरिक्त डेटा रखता है) होना चाहिए। आपके पहले कार्यान्वयन को इसके पहले मूल्य के बजाय Carउपयोग Companyकरने के Stringलिए बदलने की आवश्यकता होगी । आपका दूसरा कार्यान्वयन ठीक है, आप इसका उपयोग करते हैं Car Company String Intऔर यह पहले की तरह काम करेगा (कंपनी के डेटा तक पहुंचने के लिए निश्चित रूप से कार्यों को बदलना होगा)।


क्या आप किसी अन्य डेटा घोषणा के डेटा-संदर्भ में टाइप कंस्ट्रक्टर का उपयोग कर सकते हैं? कुछ पसंद है data Color = Blue ; data Bright = Color? मैंने इसे ghci में आज़माया, और ऐसा लगता है कि टाइप कंस्ट्रक्टर में कलर का ब्राइट डेफिनेशन में कलर डेटा कंस्ट्रक्टर से कोई लेना-देना नहीं है। सिर्फ 2 कलर कंस्ट्रक्टर हैं, एक जो डेटा है और दूसरा टाइप है।
CMCDragonkai

@CMCDragonkai मुझे नहीं लगता कि आप ऐसा कर सकते हैं, और मुझे यकीन नहीं है कि आप इसके साथ क्या हासिल करना चाहते हैं। आप "रैप" कर सकते हैं एक मौजूदा प्रकार का उपयोग कर dataया newtype(जैसे data Bright = Bright Color), या आप उपयोग कर सकते हैं typeताकि एक पर्याय (जैसे परिभाषित करने के लिए में type Bright = Color)।
लांडेई

5

दूसरे में "बहुरूपता" की धारणा है।

a b cकिसी भी प्रकार का हो सकता है। उदाहरण के लिए, aएक हो सकता है [String], bहो सकता है [Int] और cहो सकता है [Char]

जबकि पहले का प्रकार तय हो गया है: कंपनी एक है String, मॉडल एक है Stringऔर एक वर्ष है Int

कार उदाहरण बहुरूपता का उपयोग करने के महत्व को नहीं दिखा सकता है। लेकिन कल्पना करें कि आपका डेटा सूची प्रकार का है। एक सूची हो सकती है String, Char, Int ...उन स्थितियों में, आपको अपने डेटा को परिभाषित करने के दूसरे तरीके की आवश्यकता होगी।

तीसरे तरीके के अनुसार मुझे नहीं लगता कि इसे पिछले प्रकार में फिट करने की आवश्यकता है। यह हास्केल में डेटा को परिभाषित करने का सिर्फ एक अन्य तरीका है।

यह एक शुरुआत के रूप में मेरी विनम्र राय है।

Btw: सुनिश्चित करें कि आप अपने मस्तिष्क को अच्छी तरह से प्रशिक्षित करते हैं और इसके लिए सहज महसूस करते हैं। यह बाद में मोनाद को समझने की कुंजी है।


1

यह प्रकारों के बारे में है : पहले मामले में, आपके प्रकार String(कंपनी और मॉडल के लिए) और Intवर्ष के लिए निर्धारित होते हैं । दूसरे मामले में, आपके अधिक सामान्य हैं। a, bऔर cपहले उदाहरण के रूप में बहुत ही प्रकार के हो सकते हैं, या कुछ पूरी तरह से अलग हो सकते हैं। उदाहरण के लिए, पूर्णांक के बजाय वर्ष को स्ट्रिंग के रूप में देना उपयोगी हो सकता है। और यदि आप चाहें, तो आप अपने Colorप्रकार का उपयोग भी कर सकते हैं ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.