हास्केल / GHC में `forall` कीवर्ड क्या करता है?


312

मैं यह समझने लगा हूं forallकि इस तरह से "तथाकथित प्रकार" में कीवर्ड का उपयोग कैसे किया जाता है:

data ShowBox = forall s. Show s => SB s

यह केवल एक सबसेट है, हालांकि, forallइसका उपयोग कैसे किया जाता है और मैं बस इस तरह से चीजों में इसके उपयोग के आसपास अपने दिमाग को लपेट नहीं सकता हूं:

runST :: forall a. (forall s. ST s a) -> a

या यह बताते हुए कि ये अलग क्यों हैं:

foo :: (forall a. a -> a) -> (Char, Bool)
bar :: forall a. ((a -> a) -> (Char, Bool))

या पूरा RankNTypesसामान ...

मैं भाषा के प्रकार के बजाय स्पष्ट, शब्द-मुक्त अंग्रेजी पसंद करना चाहता हूं जो अकादमिक वातावरण में सामान्य हैं। इस पर मैंने जिन स्पष्टीकरणों को पढ़ने का प्रयास किया है उनमें से अधिकांश (जिन्हें मैं खोज इंजनों के माध्यम से खोज सकता हूं) में ये समस्याएं हैं:

  1. वे अधूरे हैं। वे इस कीवर्ड के उपयोग के एक हिस्से की व्याख्या करते हैं (जैसे "अस्तित्वगत प्रकार") जो मुझे तब तक खुश महसूस करता है जब तक कि मैं उस कोड को नहीं पढ़ता जो इसे पूरी तरह से अलग तरीके से उपयोग करता है (जैसे runST, fooऔर barऊपर)।
  2. वे घनीभूत रूप से उन मान्यताओं से भरे हुए हैं जो मैंने असतत गणित, श्रेणी सिद्धांत या अमूर्त बीजगणित की किसी भी शाखा में नवीनतम पढ़ा है जो इस सप्ताह लोकप्रिय है। (अगर मैं "फिर से कार्यान्वयन के विवरण के लिए जो कुछ भी कागज से परामर्श करता हूं" शब्द कभी नहीं पढ़ता हूं , तो यह बहुत जल्द होगा।)
  3. वे उन तरीकों से लिखे गए हैं जो अक्सर सरल अवधारणाओं को यातनापूर्ण रूप से मुड़ और खंडित व्याकरण और शब्दार्थ में बदल देते हैं।

इसलिए...

वास्तविक प्रश्न पर। क्या कोई भी पूरी तरह forallसे स्पष्ट, सादे अंग्रेजी में कीवर्ड की व्याख्या कर सकता है (या, अगर यह कहीं मौजूद है, तो इस तरह के स्पष्ट विवरण को इंगित करें जो मैंने याद किया है) जो यह नहीं मानता कि मैं एक गणितज्ञ हूं जो शब्दजाल में डूबा हुआ है?


जोड़ने के लिए संपादित:

नीचे उच्च-गुणवत्ता वाले लोगों के दो स्टैंड-आउट उत्तर थे, लेकिन दुर्भाग्य से मैं केवल एक को सर्वश्रेष्ठ के रूप में चुन सकता हूं। नॉर्मन का जवाब विस्तृत और उपयोगी था, चीजों को इस तरह से समझाते हुए जिसमें कुछ सैद्धांतिक आधार थे forallऔर साथ ही मुझे इसके कुछ व्यावहारिक निहितार्थ भी दिखाए। yairchu का जवाबएक ऐसे क्षेत्र को शामिल किया गया है जिसका कोई और उल्लेख नहीं किया गया है (स्कोप्ड प्रकार चर) और कोड और एक GHCi सत्र के साथ सभी अवधारणाओं को चित्रित किया है। क्या दोनों का चयन करना संभव था, मैं करूंगा। दुर्भाग्य से मैं नहीं कर सकता और दोनों जवाबों को करीब से देखने के बाद, मैंने फैसला किया है कि येरचू के नॉर्मल आउटफिट कोड और अटैच स्पष्टीकरण के कारण नॉर्मन से थोड़ा बाहर है। यह थोड़ा अनुचित है, हालाँकि, क्योंकि वास्तव में मुझे इस बात को समझने के लिए दोनों उत्तरों की आवश्यकता थी, जो forallमुझे एक प्रकार के हस्ताक्षर में देखने पर एक भयानक भावना के साथ नहीं छोड़ता है।


7
हास्केल विकी इस विषय पर काफी शुरुआती हैं।
jhegedus

जवाबों:


263

एक कोड उदाहरण के साथ शुरू करते हैं:

foob :: forall a b. (b -> b) -> b -> (a -> b) -> Maybe a -> b
foob postProcess onNothin onJust mval =
    postProcess val
    where
        val :: b
        val = maybe onNothin onJust mval

यह कोड सादे हास्केल 98 में संकलित (वाक्य रचना त्रुटि) नहीं करता है। इसे forallकीवर्ड का समर्थन करने के लिए एक्सटेंशन की आवश्यकता होती है ।

असल में, वहाँ 3 रहे हैं अलग अलग के लिए आम उपयोग forallकीवर्ड (या कम से कम यह तो लगता है ), और प्रत्येक का अपना हास्केल एक्सटेंशन है: ScopedTypeVariables, RankNTypes/ Rank2Types, ExistentialQuantification

ऊपर दिए गए कोड में उन दोनों में से किसी के साथ एक सिंटैक्स त्रुटि नहीं मिलती है, लेकिन केवल ScopedTypeVariablesसक्षम के साथ टाइप-चेक ।

अपनाया प्रकार चर:

बंद प्रकार चर whereखंडों के अंदर कोड के लिए एक निर्दिष्ट प्रकारों में मदद करता है । यह उसी के रूप में एक ही bमें बनाता है ।val :: bbfoob :: forall a b. (b -> b) -> b -> (a -> b) -> Maybe a -> b

एक भ्रामक बिंदु : आप सुन सकते हैं कि जब आप forallएक प्रकार से छोड़ते हैं तो यह वास्तव में अभी भी निहित है। ( नॉर्मन के उत्तर से: "आम तौर पर ये भाषाएं बहुरूपता के प्रकारों को छोड़ देती हैं" )। यह दावा सही है, लेकिन यह अन्य उपयोगों के लिए संदर्भित है forall, और उपयोग के लिए नहीं ScopedTypeVariables

रैंक-एन-प्रकार:

आइए इसके साथ शुरू mayb :: b -> (a -> b) -> Maybe a -> bकरें mayb :: forall a b. b -> (a -> b) -> Maybe a -> b, जब सक्षम किया जाता है , को छोड़करScopedTypeVariables

इसका मतलब है कि यह हर काम करता है aऔर b

मान लीजिए कि आप ऐसा कुछ करना चाहते हैं।

ghci> let putInList x = [x]
ghci> liftTup putInList (5, "Blah")
([5], ["Blah"])

इसका प्रकार क्या होना चाहिए liftTup? यह है liftTup :: (forall x. x -> f x) -> (a, b) -> (f a, f b)। यह देखने के लिए, आइए इसे कोड करने का प्रयास करें:

ghci> let liftTup liftFunc (a, b) = (liftFunc a, liftFunc b)
ghci> liftTup (\x -> [x]) (5, "Hello")
    No instance for (Num [Char])
    ...
ghci> -- huh?
ghci> :t liftTup
liftTup :: (t -> t1) -> (t, t) -> (t1, t1)

"हम्म .. जीएचसी का अनुमान क्यों है कि टपल में एक ही प्रकार के दो होने चाहिए? आइए बताते हैं कि उन्हें ऐसा नहीं करना है"

-- test.hs
liftTup :: (x -> f x) -> (a, b) -> (f a, f b)
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v)

ghci> :l test.hs
    Couldnt match expected type 'x' against inferred type 'b'
    ...

हम्म। इसलिए यहाँ GHC हमें लागू नहीं करता है liftFuncपर vक्योंकि v :: bऔर liftFuncएक चाहता है x। हम वास्तव में चाहते हैं कि हमारा फंक्शन एक ऐसा फंक्शन हो जो किसी भी संभव को स्वीकार करे x!

{-# LANGUAGE RankNTypes #-}
liftTup :: (forall x. x -> f x) -> (a, b) -> (f a, f b)
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v)

तो यह ऐसा नहीं है liftTupजो सभी के लिए काम करता है x, यह फ़ंक्शन है जो इसे प्राप्त करता है।

अस्तित्व मात्रा:

आइए एक उदाहरण का उपयोग करें:

-- test.hs
{-# LANGUAGE ExistentialQuantification #-}
data EQList = forall a. EQList [a]
eqListLen :: EQList -> Int
eqListLen (EQList x) = length x

ghci> :l test.hs
ghci> eqListLen $ EQList ["Hello", "World"]
2

यह रैंक-एन-प्रकार से कैसे भिन्न है?

ghci> :set -XRankNTypes
ghci> length (["Hello", "World"] :: forall a. [a])
    Couldnt match expected type 'a' against inferred type '[Char]'
    ...

रैंक-एन-प्रकार के साथ, का forall aमतलब है कि आपकी अभिव्यक्ति को हर संभव फिट होना चाहिए a। उदाहरण के लिए:

ghci> length ([] :: forall a. [a])
0

एक खाली सूची किसी भी प्रकार की सूची के रूप में काम करती है।

तो अस्तित्व-मात्रा के साथ, forallएस में dataपरिभाषाओं कि मतलब है, मान है सकते हैं का होना किसी भी उपयुक्त प्रकार, नहीं है कि यह चाहिए की हो सभी उपयुक्त प्रकार के।


ठीक है, मुझे अपने छह घंटे मिल गए और अब मैं आपके जवाब को डिकोड कर सकता हूं। :) तुम्हारे और नॉर्मन के बीच मुझे ठीक उसी तरह का जवाब मिला जिसकी मुझे तलाश थी। धन्यवाद।
JUST MY सही ओपिनियन

2
वास्तव में, आप ScopedTypeVariablesइसे इससे भी बदतर लगते हैं। यदि आप b -> (a -> b) -> Maybe a -> bइस पर इस एक्सटेंशन के साथ टाइप लिखते हैं, तब भी यह बिल्कुल बराबर होगा forall a b. b -> (a -> b) -> Maybe a -> b। हालाँकि, यदि आप उसी का संदर्भ लेना चाहते हैं b(और इसका निहितार्थ नहीं है) तो आपको स्पष्ट रूप से मात्रात्मक संस्करण लिखना होगा। अन्यथा, STVएक अत्यंत घुसपैठ विस्तार होगा।
नामिनोलो

1
@ नोमानोलो: मेरा मतलब डिमॉन से नहीं था ScopedTypeVariables, और मुझे नहीं लगता कि यह बुरा है। imho यह प्रोग्रामिंग प्रक्रिया के लिए और विशेष रूप से हास्केल शुरुआती के लिए एक बहुत ही उपयोगी उपकरण है, और मैं आभारी हूं कि यह मौजूद है।
येरचू

2
यह एक पुराना सवाल (और उत्तर) है, लेकिन यह इस तथ्य को प्रतिबिंबित करने के लिए अद्यतन करने के लायक हो सकता है कि अस्तित्व के प्रकार को जीएडीटी का उपयोग करके इस तरह से व्यक्त किया जा सकता है कि (कम से कम मेरे लिए) मात्रा को समझने में बहुत आसान बनाता है।
dfeuer

1
मुझे व्यक्तिगत रूप से अपने स्वयं के मुकाबले GADT फॉर्म में इसके अनुवाद के संदर्भ में मौजूद संकेतन को समझना / समझना आसान है, लेकिन आप अन्यथा सोचने के लिए निश्चित रूप से स्वतंत्र हैं।
डेफ़र

117

क्या कोई पूरी तरह से स्पष्ट अंग्रेजी, स्पष्ट अंग्रेजी में forall कीवर्ड की व्याख्या कर सकता है ?

नहीं। (ठीक है, शायद डॉन स्टीवर्ट कर सकते हैं।)

यहाँ एक सरल, स्पष्ट स्पष्टीकरण के अवरोध हैं या forall:

  • यह एक मात्रात्मक है। आपके पास कम से कम एक लॉजिक (विधेय परिकलन) करने के लिए एक सार्वभौमिक या अस्तित्वमान क्वांटिफायर है। यदि आपने कभी पथरी की भविष्यवाणी नहीं देखी है या क्वांटिफायर के साथ सहज नहीं हैं (और मैंने पीएचडी योग्यता परीक्षा के दौरान छात्रों को देखा है जो सहज नहीं हैं), तो आपके लिए, इसका कोई आसान विवरण नहीं है forall

  • यह एक प्रकार की मात्रा है। यदि आपने सिस्टम एफ नहीं देखा है और बहुरूप प्रकार लिखने का कुछ अभ्यास कर लिया है, तो आप forallभ्रमित होने वाले हैं। हास्केल या एमएल के साथ अनुभव पर्याप्त नहीं है, क्योंकि आम तौर पर ये भाषाएं forallबहुरंगी प्रकारों से बाहर निकलती हैं। (मेरे दिमाग में, यह एक भाषा-डिज़ाइन की गलती है।)

  • विशेष रूप से हास्केल में, forallउन तरीकों से उपयोग किया जाता है जो मुझे भ्रामक लगते हैं। (मैं एक प्रकार का सिद्धांतवादी नहीं हूं, लेकिन मेरा काम मुझे बहुत प्रकार के सिद्धांत के संपर्क में लाता है, और मैं इसके साथ काफी सहज हूं।) मेरे लिए, भ्रम का मुख्य स्रोत यह है कि forallएक प्रकार को एन्कोड करने के लिए उपयोग किया जाता है मैं खुद इसके साथ लिखना पसंद करूंगा exists। यह क्वांटिफ़ायर और तीरों को शामिल करने वाले एक प्रकार के आइसोमोर्फिज्म के एक मुश्किल बिट द्वारा उचित है, और हर बार जब मैं इसे समझना चाहता हूं, तो मुझे चीजों को देखना होगा और खुद आइसोमोर्फिज्म को काम करना होगा।

    यदि आप टाइप आइसोमॉर्फिज़्म के विचार से सहज नहीं हैं, या यदि आपके पास टाइप आइसोमॉर्फिज्म के बारे में सोचने का कोई अभ्यास नहीं है, तो इसका उपयोग forallआपको उत्तेजित करने वाला है।

  • जबकि सामान्य अवधारणा forallहमेशा समान होती है (एक प्रकार के चर को शुरू करने के लिए बाध्यकारी), विभिन्न उपयोगों का विवरण काफी भिन्न हो सकता है। विविधताओं को समझाने के लिए अनौपचारिक अंग्रेजी बहुत अच्छा साधन नहीं है। वास्तव में क्या हो रहा है यह समझने के लिए, आपको कुछ गणित की आवश्यकता है। इस मामले में संबंधित गणित बेंजामिन पियर्स के परिचयात्मक पाठ प्रकार और प्रोग्रामिंग भाषाओं में पाया जा सकता है , जो एक बहुत अच्छी किताब है।

अपने विशेष उदाहरणों के लिए,

  • runST आपके सिर पर चोट लगनी चाहिए । उच्च-रैंक प्रकार (एक तीर के बाईं ओर स्थित) शायद ही कभी जंगली में पाए जाते हैं। मैं आपको उस पेपर को पढ़ने के लिए प्रोत्साहित करता हूं जो पेश किया गया runST: "आलसी कार्यात्मक स्टेट थ्रेड्स" । यह वास्तव में अच्छा पेपर है, और यह आपको runSTविशेष रूप से और सामान्य रूप से उच्च-रैंक प्रकारों के लिए बहुत बेहतर अंतर्ज्ञान देगा । स्पष्टीकरण में कई पृष्ठ हैं, यह बहुत अच्छी तरह से किया गया है, और मैं इसे संक्षेप में बताने की कोशिश नहीं करने जा रहा हूं।

  • विचार करें

    foo :: (forall a. a -> a) -> (Char,Bool)
    bar :: forall a. ((a -> a) -> (Char, Bool))

    यदि मैं फोन करता हूं bar, तो मैं बस किसी भी प्रकार को चुन सकता हूं aजो मुझे पसंद है, और मैं इसे टाइप से टाइप aकरने के लिए एक फ़ंक्शन पास कर सकता हूं a। उदाहरण के लिए, मैं फ़ंक्शन (+1)या फ़ंक्शन को पास कर सकता हूं reverse। आप यह forallकह सकते हैं कि "मुझे अब टाइप करने के लिए मिलता है"। (प्रकार चुनने के लिए तकनीकी शब्द तात्कालिक है ।)

    कॉलिंग पर प्रतिबंध fooबहुत अधिक कड़े हैं: तर्क को बहुरूपी फ़ंक्शन foo होना चाहिए। उस प्रकार के साथ, केवल कार्यों मैं करने के लिए पारित कर सकते हैं fooकर रहे हैं idया एक समारोह है कि हमेशा diverges या त्रुटियों, जैसे undefined। कारण के साथ वह यह है कि foo, forall, तीर के बाईं ओर है तो के रूप में की कॉलर fooमैं लेने के लिए क्या नहीं मिलता aहै-बल्कि यह है कार्यान्वयन की fooकि लेने के लिए क्या हो जाता aहै। क्योंकि forallतीर के बाईं ओर है, तीर के ऊपर के बजाय के रूप में bar, तात्कालिकता कॉल साइट पर बजाय समारोह के शरीर में जगह लेता है।

सारांश: एक पूरा का विवरण forallकीवर्ड गणित की आवश्यकता है और केवल कोई है जो गणित का अध्ययन किया है से समझा जा सकता। यहां तक ​​कि आंशिक स्पष्टीकरण गणित के बिना समझना मुश्किल है। लेकिन शायद मेरी आंशिक, गैर-गणित व्याख्याएं थोड़ी मदद करती हैं। लॉन्चबरी और पिएटन जोन्स पर पढ़ें runST!


परिशिष्ट: शब्द "ऊपर", "नीचे", "बाईं ओर"। इनका पाठकीय तरीकों से कोई लेना-देना नहीं है और अमूर्त-वाक्यविन्यास पेड़ों के साथ सब कुछ करना है। अमूर्त वाक्य रचना में, एक forallप्रकार के चर का नाम लेता है, और फिर एक पूर्ण प्रकार "नीचे" होता है। एक तीर दो प्रकार (तर्क और परिणाम प्रकार) लेता है और एक नया प्रकार (फ़ंक्शन प्रकार) बनाता है। तर्क प्रकार "तीर के बाईं ओर" है; यह अमूर्त-वाक्य रचना के पेड़ में तीर का बायाँ बच्चा है।

उदाहरण:

  • में forall a . [a] -> [a], फ़ॉरल तीर के ऊपर है; तीर के बाईं ओर क्या है [a]

  • में

    forall n f e x . (forall e x . n e x -> f -> Fact x f) 
                  -> Block n e x -> f -> Fact x f

    कोष्ठक के प्रकार को "एक तीर के बाईं ओर एक कांटा" कहा जाएगा। (मैं इस तरह के एक अनुकूलक का उपयोग कर रहा हूँ, जिस पर मैं काम कर रहा हूँ।)


वास्तव में मुझे इसके बारे में सोचने के बिना ऊपर / नीचे / बाईं ओर मिला। मैं एक सुस्त हूं, हां, लेकिन एक बूढ़ा सुस्त हूं जिसे पहले उस सामान के साथ कुश्ती करनी थी। (अन्य लोगों के बीच ASN.1 संकलक लेखन।), हालांकि परिशिष्ट के लिए धन्यवाद।
JUST MY सही ओपिनियन

12
@ जस्ट थैंक्स लेकिन मैं पोस्टरिटी के लिए लिख रहा हूं। मैंने एक से अधिक प्रोग्रामर में भाग लिया है जो सोचता है कि forall a . [a] -> [a]फ़ॉरेस्ट तीर के बाईं ओर है।
नॉर्मन रैमसे

ठीक है, अपने जवाब पर विस्तार से जा रहा हूं, अब, मुझे अपने दिल के नीचे से, नॉर्मन को धन्यवाद देना होगा। सामान का एक बहुत जोर से अब क्लिक करें एक साथ जगह में गिर गया है, और सामान है कि मैं अभी भी मुझे समझ नहीं आता कि कम से कम समझते हैं कि मैं नहीं कर रहा हूँ मतलब यह समझना महत्वपूर्ण है और बस के ऊपर से गुजरती होगा forallउन परिस्थितियों में के रूप में, प्रभावी ढंग से, लाइन शोर। मैं उस पेपर को देखूंगा जिसे आपने लिंक किया है (लिंक के लिए भी धन्यवाद!) और देखें कि क्या यह मेरी समझ के दायरे में है। कुडोस।
JUST MY सही ओपिनियन

10
मैंने बाएं पढ़ा और मैंने देखा, सचमुच, छोड़ दिया। जब तक आपने "पार्स ट्री" नहीं कहा, तब तक यह मेरे लिए बहुत अस्पष्ट था।
पॉल नाथन

पियर्स की किताब के लिए सूचक के लिए धन्यवाद। इसमें सिस्टम एफ की बहुत स्पष्ट व्याख्या है। यह बताता है कि क्यों existsलागू नहीं किया गया था। (यह सिस्टम एफ का हिस्सा नहीं है!) हास्केल में, सिस्टम एफ का हिस्सा अंतर्निहित है, लेकिन forallउन चीजों में से एक है जो पूरी तरह से गलीचा के नीचे बह नहीं सकते हैं। यह ऐसा है जैसे कि उन्होंने हिंडले-मिलनर के साथ शुरुआत की, जिसे forallअंतर्निहित किए जाने की अनुमति होगी , और फिर अधिक शक्तिशाली प्रकार की प्रणाली का विकल्प चुना जाएगा, जिससे हममें से वे भ्रमित हो जाएं जिन्होंने FOL के 'forall ’और' अस्तित्व’ का अध्ययन किया और वहां रुक गए।
T_S_

50

मेरा मूल उत्तर:

क्या कोई भी स्पष्ट रूप से स्पष्ट अंग्रेजी में forall कीवर्ड की व्याख्या कर सकता है

जैसा कि नॉर्मन इंगित करता है, टाइप सिद्धांत से एक तकनीकी शब्द का स्पष्ट, सादा अंग्रेजी स्पष्टीकरण देना बहुत कठिन है। हम सब हालांकि कोशिश कर रहे हैं।

'फोरल' के बारे में याद रखने के लिए वास्तव में केवल एक चीज है: यह कुछ हद तक प्रकारों को बांधता है । एक बार जब आप समझते हैं कि, सब कुछ काफी आसान है। यह प्रकार के स्तर पर 'लैम्ब्डा' (या 'लेट' का एक रूप) के बराबर है - नॉर्मन रैमसे ने अपने उत्कृष्ट उत्तर में गुंजाइश की इसी अवधारणा को व्यक्त करने के लिए "बाएं" / "ऊपर" की धारणा का उपयोग किया है ।

'Forall' के अधिकांश उपयोग बहुत सरल हैं, और आप उन्हें GHC उपयोगकर्ता नियमावली, S7.8 में प्रस्तुत कर सकते हैं , विशेष रूप से 'forall' के नेस्टेड रूपों पर उत्कृष्ट S7.8.5

हास्केल में, हम आम तौर पर प्रकारों के लिए बाइंडर को छोड़ देते हैं, जब प्रकार सार्वभौमिक रूप से quanitified होता है, जैसे:

length :: forall a. [a] -> Int

के बराबर है:

length :: [a] -> Int

बस।

चूँकि आप अब प्रकार के चर को किसी दायरे में बाँध सकते हैं, आप अपने पहले उदाहरण की तरह शीर्ष स्तर (" सार्वभौमिक रूप से परिमाणित ") के अलावा अन्य स्थानों पर भी स्कोप रख सकते हैं , जहाँ टाइप वैरिएबल केवल डेटा संरचना के भीतर दिखाई देता है। यह छिपे हुए प्रकार (" अस्तित्वगत प्रकार ") के लिए अनुमति देता है । या हम बाइंडिंग ("रैंक एन प्रकार") के मनमाने ढंग से घोंसले के शिकार हो सकते हैं ।

टाइप सिस्टम को गहराई से समझने के लिए, आपको कुछ शब्दजाल सीखने की आवश्यकता होगी। यह कंप्यूटर विज्ञान की प्रकृति है। हालांकि, सरल उपयोग, ऊपर की तरह, मूल्य स्तर पर 'लेट' के साथ सादृश्य के माध्यम से, सहज ज्ञान युक्त समझा जा सकता है। एक शानदार परिचय है लॉन्चबरी और पेयटन जोन्स


4
तकनीकी रूप से, सक्षम होने के length :: forall a. [a] -> Intबराबर नहीं है। जब वहाँ है, यह प्रभावित करता है के खंड (अगर यह एक है) और नामित प्रकार चर का अर्थ बदल उस में। length :: [a] -> IntScopedTypeVariablesforall a.lengthwherea
येरचू

2
वास्तव में। ScopedTypeVariables कहानी को थोड़ा जटिल करता है।
डॉन स्टीवर्ट

3
@DonStewart, "यह आपके विवरण में" कुछ प्रकारों को "बेहतर प्रकार से बांधता है" के रूप में "यह कुछ चर के प्रकार प्रकार को बांधता है" हो सकता है?
रोमियो

31

वे घनीभूत रूप से उन मान्यताओं से भरे हुए हैं जो मैंने असतत गणित, श्रेणी सिद्धांत या अमूर्त बीजगणित की किसी भी शाखा में नवीनतम पढ़ा है जो इस सप्ताह लोकप्रिय है। (यदि मैं "फिर से कार्यान्वयन के विवरण के लिए जो कुछ भी कागज से परामर्श करता हूं" शब्द कभी नहीं पढ़ता हूं, तो यह बहुत जल्द होगा।)

एर, और पहले क्रम के तर्क के बारे में क्या? सार्वभौमिक परिमाणीकरण केforall संदर्भ में बहुत स्पष्ट रूप से है , और इस संदर्भ में शब्द अस्तित्व के रूप में अच्छी तरह से अधिक समझ में आता है, हालांकि यह कम अजीब होता अगर कोई कीवर्ड होता। चाहे परिमाणीकरण प्रभावी रूप से सार्वभौमिक हो या अस्तित्वगत हो, यह मात्रात्मक के स्थान पर निर्भर करता है कि किसी फ़ंक्शन एरो के किस ओर चर का उपयोग किया जाता है और यह सब थोड़ा भ्रमित है।exists

इसलिए, यदि वह मदद नहीं करता है, या यदि आप सिर्फ प्रतीकात्मक तर्क पसंद नहीं करते हैं, तो एक अधिक कार्यात्मक प्रोग्रामिंग-ईश परिप्रेक्ष्य से आप फ़ंक्शन के लिए बस (निहित) प्रकार के मापदंडों के प्रकार के बारे में सोच सकते हैं । इस अर्थ में टाइप पैरामीटर लेने वाले फ़ंक्शंस पारंपरिक रूप से किसी भी कारण से एक कैपिटल लैंबडा का उपयोग करके लिखे जाते हैं, जो मैं यहां लिखूंगा /\

इसलिए, idफ़ंक्शन पर विचार करें :

id :: forall a. a -> a
id x = x

हम इसे लैम्बदास के रूप में फिर से लिख सकते हैं, "सिग्नेचर टाइप" को टाइप सिग्नेचर से बाहर निकालकर इनलाइन टाइप एनोटेशन जोड़ सकते हैं:

id = /\a -> (\x -> x) :: a -> a

यहाँ वही किया जाता है const:

const = /\a b -> (\x y -> x) :: a -> b -> a

तो आपका barकार्य कुछ इस तरह हो सकता है:

bar = /\a -> (\f -> ('t', True)) :: (a -> a) -> (Char, Bool)

ध्यान दें कि barतर्क के रूप में दिए गए फ़ंक्शन का barप्रकार 's प्रकार के पैरामीटर पर निर्भर करता है । विचार करें कि क्या आपके पास इसके बजाय ऐसा कुछ था:

bar2 = /\a -> (\f -> (f 't', True)) :: (a -> a) -> (Char, Bool)

यहां bar2फ़ंक्शन को कुछ प्रकार से लागू किया जा रहा है Char, इसलिए bar2किसी भी प्रकार के पैरामीटर को छोड़कर अन्य Charप्रकार की त्रुटि का कारण होगा।

दूसरी ओर, यहाँ पर ऐसा fooलग सकता है:

foo = (\f -> (f Char 't', f Bool True))

इसके विपरीत bar, fooवास्तव में किसी भी प्रकार के मापदंडों को नहीं लेता है! यह एक फ़ंक्शन लेता है जो स्वयं एक प्रकार का पैरामीटर लेता है, फिर उस फ़ंक्शन को दो अलग-अलग प्रकारों पर लागू करता है ।

इसलिए जब आप forallएक प्रकार का हस्ताक्षर देखते हैं, तो इसे केवल प्रकार के हस्ताक्षर के लिए एक लंबोदर अभिव्यक्ति के रूप में सोचें । नियमित लंबोदर की तरह, दायरा forallसम्‍मिलित करने के लिए, जहाँ तक संभव हो सके दाईं ओर फैली हुई गुंजाइश , और नियमित लंबोदर में बंधे हुए चरों की तरह, प्रकार चर जो forallकेवल परिमाणित अभिव्यक्ति के दायरे में हैं।


पोस्ट स्क्रिप्टम : शायद आपको आश्चर्य हो सकता है - अब जब हम प्रकार के मापदंडों को लेने वाले कार्यों के बारे में सोच रहे हैं, तो हम उन मापदंडों के साथ कुछ और अधिक दिलचस्प क्यों नहीं कर सकते हैं, उन्हें एक प्रकार के हस्ताक्षर में डाल दिया जाए? जवाब है कि हम कर सकते हैं!

एक फ़ंक्शन जो एक लेबल के साथ प्रकार चर डालता है और एक नया प्रकार देता है एक प्रकार का निर्माता है , जिसे आप कुछ इस तरह से लिख सकते हैं:

Either = /\a b -> ...

लेकिन हमें पूरी तरह से नए संकेतन की आवश्यकता होगी, क्योंकि जिस तरह से इस तरह का लिखा जाता है, जैसे Either a b, पहले से ही " Eitherइन मापदंडों पर फ़ंक्शन लागू करें" का सुझाव है ।

दूसरी ओर, एक फ़ंक्शन जो अपने प्रकार के मापदंडों पर "पैटर्न से मेल खाता है", विभिन्न प्रकारों के लिए अलग-अलग मान लौटाता है, एक प्रकार की कक्षा का एक तरीका है/\ऊपर मेरे सिंटैक्स के लिए थोड़ा विस्तार इस तरह से कुछ सुझाव देता है:

fmap = /\ f a b -> case f of
    Maybe -> (\g x -> case x of
        Just y -> Just b g y
        Nothing -> Nothing b) :: (a -> b) -> Maybe a -> Maybe b
    [] -> (\g x -> case x of
        (y:ys) -> g y : fmap [] a b g ys 
        []     -> [] b) :: (a -> b) -> [a] -> [b]

व्यक्तिगत रूप से, मुझे लगता है कि मैं हास्केल के वास्तविक वाक्य विन्यास को पसंद करता हूं ...

एक फ़ंक्शन जो अपने पैटर्न के मापदंडों से "मेल खाता है" और एक मनमाना रिटर्न देता है, मौजूदा प्रकार एक प्रकार का परिवार या कार्यात्मक निर्भरता है - पूर्व के मामले में, यह पहले से ही फ़ंक्शन परिभाषा की तरह एक महान सौदा दिखता है।


1
एक दिलचस्प यहाँ ले। यह मुझे उस समस्या पर हमले का एक और कोण देता है जो लंबी अवधि में फलदायी साबित हो सकता है। धन्यवाद।
JUST MY सही OPINION

@ केनीटीएम: या λउस मामले के लिए, लेकिन जीएचसी के यूनिकोड सिंटैक्स एक्सटेंशन का समर्थन नहीं करता है क्योंकि λ एक पत्र है , एक दुर्भाग्यपूर्ण तथ्य जो काल्पनिक रूप से मेरे काल्पनिक बड़े-लंबोदर सार पर भी लागू होगा। इसलिए के /\ अनुरूप है \ । मुझे लगता है कि मैं सिर्फ इस्तेमाल किया जा सकता था, लेकिन मैं विधेय गणना से बचने की कोशिश कर रहा था ...
सीए मैककैन

29

यहाँ सादे शब्दों में एक त्वरित और गंदी व्याख्या है जिससे आप पहले से परिचित हैं।

forallकीवर्ड वास्तव में केवल हास्केल में एक तरह से किया जाता है। हमेशा एक ही चीज का मतलब है जब आप इसे देखते हैं।

सार्वभौमिक मात्रा का ठहराव

एक सार्वभौमिक मात्रा निर्धारित प्रकार का एक प्रकार है forall a. f a। उस प्रकार के एक मूल्य को एक फ़ंक्शन के रूप में सोचा जा सकता है जो एक प्रकार a को अपने तर्क के रूप में लेता है और प्रकार के मूल्य को वापस करता है f a। सिवाय इसके कि हास्केल में इन प्रकार के तर्कों को निहित रूप से टाइप सिस्टम द्वारा पारित किया जाता है। इस "फ़ंक्शन" को आपको वही मूल्य देना पड़ता है जो कोई भी प्रकार नहीं प्राप्त करता है, इसलिए यह मूल्य बहुरूपी है

उदाहरण के लिए, प्रकार पर विचार करें forall a. [a]। उस प्रकार का एक मान दूसरा प्रकार लेता है और aआपको उसी प्रकार के तत्वों की सूची वापस देता है a। केवल एक संभावित कार्यान्वयन है, निश्चित रूप से। यह आपको खाली सूची देना होगा क्योंकि aबिल्कुल किसी भी प्रकार का हो सकता है। खाली सूची एकमात्र सूची मान है जो अपने तत्व प्रकार में बहुरूपी है (क्योंकि इसमें कोई तत्व नहीं है)।

या प्रकार forall a. a -> a। ऐसे फ़ंक्शन का कॉलर एक प्रकार aऔर मूल्य दोनों प्रदान करता है a। इसके बाद कार्यान्वयन को उसी प्रकार के मूल्य को वापस करना पड़ता है a। फिर से केवल एक ही संभव कार्यान्वयन है। उसे उसी मूल्य को वापस करना होगा जो उसे दिया गया था।

अस्तित्व की मात्रा का ठहराव

एक existentially मात्रा निर्धारित प्रकार प्रपत्र होता exists a. f a, अगर हास्केल समर्थित कि अंकन। उस प्रकार के एक मूल्य को एक जोड़ी (या "उत्पाद") के रूप में माना जा सकता है जिसमें एक प्रकार aऔर एक प्रकार का मूल्य होता है f a

उदाहरण के लिए, यदि आपके पास प्रकार का मूल्य है, तो आपके पास exists a. [a]कुछ प्रकार के तत्वों की एक सूची है। यह किसी भी प्रकार का हो सकता है, लेकिन यहां तक ​​कि अगर आपको नहीं पता कि यह क्या है तो बहुत कुछ आप इस तरह की सूची में कर सकते हैं। आप इसे उलट सकते हैं, या आप तत्वों की संख्या की गणना कर सकते हैं, या कोई अन्य सूची ऑपरेशन कर सकते हैं जो तत्वों के प्रकार पर निर्भर नहीं करता है।

ठीक है, तो एक मिनट रुको। हास्केल forallनिम्नलिखित की तरह "अस्तित्ववादी" प्रकार को दर्शाने के लिए क्यों उपयोग करता है ?

data ShowBox = forall s. Show s => SB s

यह भ्रामक हो सकता है, लेकिन यह वास्तव में डेटा निर्माता के प्रकार का वर्णन कर रहा हैSB :

SB :: forall s. Show s => s -> ShowBox

एक बार निर्माण के बाद, आप ShowBoxदो चीजों से मिलकर प्रकार के मूल्य के बारे में सोच सकते हैं। यह एक प्रकार sहै जिसमें एक प्रकार का मान होता है s। दूसरे शब्दों में, यह एक अस्तित्वगत मात्रा के प्रकार का एक मूल्य है। ShowBoxवास्तव में के रूप में लिखा जा सकता है exists s. Show s => s, अगर हास्केल ने उस संकेतन का समर्थन किया।

runST और मित्र

यह देखते हुए कि ये कैसे भिन्न हैं?

foo :: (forall a. a -> a) -> (Char,Bool)
bar :: forall a. ((a -> a) -> (Char, Bool))

पहले ले चलो bar। यह एक प्रकार aऔर एक प्रकार का कार्य a -> aकरता है, और प्रकार का एक मूल्य पैदा करता है (Char, Bool)। हम इसके Intरूप में चुन सकते हैं aऔर इसे Int -> Intउदाहरण के लिए एक प्रकार का फ़ंक्शन दे सकते हैं । लेकिन fooअलग है। इसके लिए आवश्यक है कि जिस fooप्रकार का कार्य हम इसे देना चाहते हैं उसे लागू करने में सक्षम हो। तो केवल एक ही कार्य हम यथोचित रूप से दे सकते हैं id

अब हमें इस प्रकार के अर्थ से निपटने में सक्षम होना चाहिए runST:

runST :: forall a. (forall s. ST s a) -> a

तो runSTप्रकार के मूल्य का उत्पादन करने में सक्षम होना चाहिए a, कोई फर्क नहीं पड़ता कि हम किस प्रकार को देते हैं a। ऐसा करने के लिए, यह प्रकार के एक तर्क का उपयोग करता है forall s. ST s aजो निश्चित रूप से किसी तरह का उत्पादन करना चाहिए a। क्या अधिक है, यह किसी भी प्रकार के मूल्य का उत्पादन करने में सक्षम होना चाहिए, aचाहे वह किस प्रकार का runSTनिर्णय किस प्रकार का निर्णय दे s

ठीक है तो क्या हुआ? लाभ यह है कि इससे कॉल करने वाले पर अड़चन आती runSTहै कि aप्रकार sमें सभी प्रकार शामिल नहीं हो सकते हैं । ST s [s]उदाहरण के लिए, आप इसे प्रकार का मान नहीं दे सकते । व्यवहार में इसका मतलब यह है कि कार्यान्वयन runSTप्रकार के मूल्य के साथ उत्परिवर्तन करने के लिए स्वतंत्र है s। प्रकार की गारंटी देता है कि यह म्यूटेशन के कार्यान्वयन के लिए स्थानीय है runST

का प्रकार रैंक -2 बहुरूपी प्रकारrunST का एक उदाहरण है क्योंकि इसके तर्क के प्रकार में एक मात्रा है। ऊपर का प्रकार भी रैंक 2 का है। एक साधारण बहुरूपी प्रकार, जैसा कि रैंक -1 है, लेकिन यह रैंक -2 हो जाता है यदि प्रकार के तर्कों को अपने स्वयं के क्वांटिफायर के साथ बहुरूपिक होने की आवश्यकता होती है । और यदि कोई फ़ंक्शन रैंक -2 तर्क देता है तो उसका प्रकार रैंक -3 है, और इसी तरह। सामान्य तौर पर, एक प्रकार जो रैंक के बहुरूपी तर्क लेता है, रैंक होता है ।forallfoobarforallnn + 1


11

क्या कोई भी पूरी तरह से स्पष्ट, स्पष्ट अंग्रेजी में (या, यदि यह कहीं मौजूद है, तो इस तरह के एक स्पष्ट विवरण की ओर इशारा करता है, जो मैंने याद किया है) समझा सकता है, यह नहीं मानता कि मैं एक गणितज्ञ हूं जो शब्दजाल में डूबा हुआ है?

मैं forallहास्केल और इसके प्रकार प्रणालियों के संदर्भ में सिर्फ अर्थ और शायद आवेदन के बारे में बताने की कोशिश करने जा रहा हूं ।

लेकिन इससे पहले कि आप समझें कि मैं आपको एक बहुत ही सुलभ और अच्छी बात के लिए निर्देशित करना चाहता हूं, जो रनर बजरसन ने "कॉन्स्ट्रेन्ट्स लिबरेट, लिबर्टीज कॉन्स्ट्रेन" शीर्षक से दिया है । बात इस कथन का समर्थन करने के लिए वास्तविक दुनिया उपयोग मामलों के साथ-साथ स्काला में उदाहरणों से भरी है, हालांकि यह उल्लेख नहीं करता है forall। मैं forallनीचे दिए गए परिप्रेक्ष्य को समझाने की कोशिश करूंगा ।

                CONSTRAINTS LIBERATE, LIBERTIES CONSTRAIN

निम्नलिखित विवरण के साथ आगे बढ़ने के लिए इस कथन को पचाने और विश्वास करने के लिए इसका बहुत महत्वपूर्ण है, इसलिए मैं आपसे बात करने का आग्रह करता हूं (कम से कम भागों में)।

अब एक बहुत ही सामान्य उदाहरण है, हास्केल प्रकार प्रणाली की स्पष्टता दिखाना इस प्रकार का हस्ताक्षर है:

foo :: a -> a

ऐसा कहा जाता है कि इस प्रकार के हस्ताक्षर को देखते हुए, केवल एक फ़ंक्शन है जो इस प्रकार को संतुष्ट कर सकता है और वह identityफ़ंक्शन है या जो अधिक लोकप्रिय रूप से जाना जाता है id

हास्केल सीखने की शुरुआत के चरणों में, मैंने हमेशा नीचे दिए गए कार्यों को सोचा:

foo 5 = 6

foo True = False

वे दोनों उपरोक्त प्रकार के हस्ताक्षर को संतुष्ट करते हैं, फिर हास्केल लोगों का दावा क्यों है कि यह idअकेला है जो प्रकार के हस्ताक्षर को संतुष्ट करता है?

ऐसा इसलिए है क्योंकि forallटाइप सिग्नेचर में एक निहित छिपा है। वास्तविक प्रकार है:

id :: forall a. a -> a

तो, अब हम इस कथन पर वापस आते हैं: विवशता से मुक्ति मिलती है, स्वतंत्रता में बाधा आती है

इस प्रकार की प्रणाली में अनुवाद करना, यह कथन बन जाता है:

प्रकार के स्तर पर एक बाधा, शब्द स्तर पर एक स्वतंत्रता बन जाती है

तथा

प्रकार के स्तर पर एक स्वतंत्रता, शब्द स्तर पर एक बाधा बन जाती है


आइए हम पहले कथन को सिद्ध करने का प्रयास करें:

प्रकार स्तर पर एक बाधा ..

तो हमारे प्रकार हस्ताक्षर पर एक बाधा डाल रहा है

foo :: (Num a) => a -> a

शब्द स्तर पर एक स्वतंत्रता बन जाती है जो हमें इन सभी को लिखने की स्वतंत्रता या लचीलापन प्रदान करती है

foo 5 = 6
foo 4 = 2
foo 7 = 9
...

उसी को aकिसी अन्य टाइपकास्ट आदि के साथ विवश करके देखा जा सकता है

तो अब इस प्रकार के हस्ताक्षर: का foo :: (Num a) => a -> aअनुवाद है:

a , st a -> a, a  Num

इसे अस्तित्वगत परिमाणीकरण के रूप में जाना जाता है, जो वहां अनुवाद करता है, जिसके कुछ उदाहरण मौजूद हैं , जिसके aलिए एक प्रकार की चीज खिलाए जाने पर एक फ़ंक्शन aउसी प्रकार का कुछ रिटर्न देता है, और वे सभी उदाहरण संख्याओं के सेट से संबंधित होते हैं।

इसलिए हम एक बाधा को जोड़कर देख सकते हैं (जो aसंख्याओं के सेट से संबंधित होना चाहिए), कई संभावित कार्यान्वयन के लिए शब्द स्तर को मुक्त करता है।


अब दूसरे कथन पर आते हैं और जो वास्तव में इसका स्पष्टीकरण देता है forall:

प्रकार के स्तर पर एक स्वतंत्रता, शब्द स्तर पर एक बाधा बन जाती है

तो अब हम फंक्शन को टाइप लेवल पर फ्री करते हैं:

foo :: forall a. a -> a

अब यह अनुवाद करता है:

a , a -> a

जिसका अर्थ है कि इस प्रकार के हस्ताक्षर का कार्यान्वयन ऐसा होना चाहिए कि यह a -> aसभी परिस्थितियों के लिए हो।

इसलिए अब यह हमें टर्म स्तर पर विवश करने लगा है। हम अब नहीं लिख सकते

foo 5 = 7

क्योंकि यह कार्यान्वयन संतुष्ट नहीं होगा यदि हम एक के aरूप में डालते हैं Boolaएक हो सकता है Charया एक [Char]या एक कस्टम डेटाप्रकार। सभी परिस्थितियों में इसे समान प्रकार का कुछ वापस करना चाहिए। इस प्रकार के स्तर पर स्वतंत्रता को यूनिवर्सल क्वांटिफिकेशन और एकमात्र फ़ंक्शन के रूप में जाना जाता है जो इसे संतुष्ट कर सकता है

foo a = a

जिसे आमतौर पर identityफ़ंक्शन के रूप में जाना जाता है


इसलिए forallएक libertyप्रकार के स्तर पर है, जिसका वास्तविक उद्देश्य constrainकिसी विशेष कार्यान्वयन के लिए शब्द स्तर है।


9

इस कीवर्ड के अलग-अलग उपयोग होने का कारण यह है कि यह वास्तव में कम से कम दो अलग-अलग प्रकार के सिस्टम एक्सटेंशन में उपयोग किया जाता है: उच्च-रैंक प्रकार, और अस्तित्व।

शायद यह सबसे अच्छा है कि केवल उन दो चीजों को अलग-अलग पढ़ें और समझें, बजाय इसके कि 'forall ’का स्पष्टीकरण प्राप्त करने की कोशिश करने के बजाय दोनों एक ही समय में वाक्यविन्यास का एक उपयुक्त बिट है।


3

अस्तित्वगत अस्तित्व कैसे है?

अस्तित्व-मात्रा के साथ, forallमें रों dataपरिभाषाओं कि मतलब है, मान है सकते हैं का होना किसी भी उपयुक्त प्रकार, नहीं है कि यह चाहिए की हो सभी उपयुक्त प्रकार के। - याचिरू का जवाब

क्यों की एक व्याख्या forallमें dataपरिभाषाओं isomorphic को कर रहे हैं (exists a. a)(छद्म हास्केल) में पाया जा सकता wikibooks के "हास्केल / existentially मात्रा निर्धारित प्रकार"

निम्नलिखित एक संक्षिप्त शब्दशः सारांश है:

data T = forall a. MkT a -- an existential datatype
MkT :: forall a. a -> T -- the type of the existential constructor

जब पैटर्न-मिलान / डिकंस्ट्रक्टिंग MkT x, किस प्रकार का है x?

foo (MkT x) = ... -- -- what is the type of x?

xकोई भी प्रकार हो सकता है (जैसा कि कहा गया है forall), और इसलिए यह प्रकार है:

x :: exists a. a -- (pseudo-Haskell)

इसलिए, निम्नलिखित आइसोमॉर्फिक हैं:

data T = forall a. MkT a -- an existential datatype
data T = MkT (exists a. a) -- (pseudo-Haskell)

forall का मतलब होता है forall

इस सब की मेरी सरल व्याख्या है, " forallवास्तव में 'का अर्थ है सभी के लिए"। बनाने के लिए एक महत्वपूर्ण अंतर परिभाषा बनाम फ़ंक्शन एप्लिकेशनforall पर प्रभाव है ।

A का forallअर्थ है मान या कार्य की परिभाषा बहुरूपी होनी चाहिए।

यदि परिभाषित की जा रही बात एक बहुरूपिक मूल्य है , तो इसका मतलब है कि मूल्य सभी उपयुक्त के लिए मान्य होना चाहिए a, जो काफी प्रतिबंधक है।

यदि परिभाषित की जा रही बात एक बहुरूपी फ़ंक्शन है , तो इसका मतलब है कि फ़ंक्शन सभी उपयुक्त के लिए मान्य होना चाहिए a, जो कि प्रतिबंधात्मक नहीं है क्योंकि सिर्फ इसलिए कि फ़ंक्शन बहुरूपी है इसका मतलब यह नहीं है कि लागू किया जा रहा पैरामीटर बहुरूपी होना है। यही है, यदि फ़ंक्शन सभी के लिए मान्य है a, तो इसके विपरीत फ़ंक्शन के लिए उपयुक्त कोई भी लागू कियाa जा सकता है । हालाँकि, पैरामीटर का प्रकार केवल फ़ंक्शन परिभाषा में एक बार चुना जा सकता है।

यदि एक forallसमारोह पैरामीटर के प्रकार के अंदर है (यानी, एक Rank2Type) तो इसका मतलब है लागू पैरामीटर होना चाहिए वास्तव में करने के विचार के अनुरूप होना करने के लिए बहुरूपी, forallसाधन परिभाषा बहुरूपी है। इस मामले में, पैरामीटर का प्रकार फ़ंक्शन परिभाषा में एक से अधिक बार चुना जा सकता है ( "और फ़ंक्शन के कार्यान्वयन द्वारा चुना जाता है", जैसा कि नॉर्मन द्वारा बताया गया है )

इसलिए, अस्तित्व संबंधी dataपरिभाषाएं किसी a को भी अनुमति देती हैं , क्योंकि डेटा कंस्ट्रक्टर एक बहुरूपी फ़ंक्शन है :

MkT :: forall a. a -> T

एमकेटी का प्रकार :: a -> *

जिसका अर्थ है कि कोई भी aफ़ंक्शन पर लागू हो सकता है। जैसा कि, एक बहुरूपिक मूल्य के विपरीत :

valueT :: forall a. [a]

मान की तरह :: a

जिसका अर्थ है कि मूल्य की परिभाषा बहुरूपी होनी चाहिए। इस मामले में, सभी प्रकार की valueTखाली सूची []के रूप में परिभाषित किया जा सकता है ।

[] :: [t]

मतभेद

भले ही इसके लिए अर्थ forallसंगत है ExistentialQuantificationऔर RankNType, अस्तित्व में अंतर है क्योंकि dataकंस्ट्रक्टर का उपयोग पैटर्न मिलान में किया जा सकता है। जैसा कि ghc उपयोगकर्ता गाइड में प्रलेखित है :

जब पैटर्न मिलान, प्रत्येक पैटर्न मैच एक नया, अलग, प्रत्येक अस्तित्व प्रकार प्रकार के लिए परिचय देता है। इन प्रकारों को किसी अन्य प्रकार से एकीकृत नहीं किया जा सकता है, न ही वे पैटर्न मैच के दायरे से बच सकते हैं।

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