2017-02-05 5 views
10

this जवाब के बाद, मैं अपने कार्यक्रम में एक सामान्य लिफ्ट समारोह को क्रियान्वित किया है:मोनाड '>> =' फ़ंक्शन में फ़ॉलल को समझना?

liftTupe :: (x -> c x) -> (a, b) -> (c a, c b) --This will error 
liftTuple :: (forall x. x -> c x) -> (a, b) -> (c a, c b) 

मैं समझता हूं कि इस संदर्भ में, forallx सक्षम कर रहा है किसी भी प्रकार की हो ([], Maybe आदि ..) ।

class Applicative m => Monad m where 
    (>>=) :: forall a b. m a -> (a -> m b) -> m b 

मैं समारोह परिभाषा इस forall की भूमिका को समझ में नहीं कर सकते हैं:

मैं अब monads में >>= की परिभाषा में देख रहा हूँ? जैसा कि liftTuple के विपरीत, यह किसी विशिष्ट फ़ंक्शन (x -> c x) से बाध्य नहीं है?

+5

सुनिश्चित नहीं हैं कि क्यों सभी प्रश्नों के उत्तर तो अधिक शब्दों वाले हैं। एक वाक्य में: आप सही हैं; यह कुछ भी नहीं बदलता है और स्पष्ट होने के लिए बस वहां है। – Ryan

+0

'के लिए एक बी। <..> '' = '* * के प्रकार में * एक विशिष्ट फ़ंक्शन के लिए बाध्य है - फ़ंक्शन 'एम ए -> (ए -> एम बी) -> एम बी'। आपके पास फ़ंक्शन के बिना 'forall' भी हो सकता है, उदा। '[] :: फोरल ए। [ए] ',' खाली :: फोरल एफ ए। वैकल्पिक एफ => एफ ए'। – user2407038

+1

@Ryan जब मुझे जवाब मिलता है: "क्योंकि सबकुछ पूरी तरह योग्य है।" मेरा अनुवर्ती प्रश्न अक्सर "क्यों?" होता है। – ThreeFx

उत्तर

6

असल में, जब आप forall का उपयोग नहीं करते हैं, तो सभी प्रकार फ़ंक्शन परिभाषा में वैश्विक होते हैं, जिसका अर्थ यह है कि फ़ंक्शन कहलाते समय वे सभी को हटाए जाते हैं। forall के साथ आप आगे बढ़ सकते हैं कि फ़ंक्शन के लिए x ले जाने तक इसे स्वयं कहा जाता है।

तो पहले एक में आप एक समारोह जो x लेता है और c x देता है, तो आप a और b के साथ एक टपल है और आप c a और c b के साथ एक टपल की उम्मीद है। चूंकि आपने पहले ही कहा है कि पहला फ़ंक्शन x स्वीकार करता है, आप xa के समान बन सकते हैं, लेकिन यह b नहीं होगा, इसलिए x पूरी घोषणा के लिए एक बार परिभाषित किया गया है। तो आप फ़ंक्शन को a और b दोनों स्वीकार नहीं कर सकते हैं।

हालांकि, दूसरे मामले में x गुंजाइश x लेने वाले फ़ंक्शन तक ही सीमित है। हम मूल रूप से कह रहे हैं कि एक ऐसा कार्य है जो कुछ लेता है और c बनाता है, और यह किसी भी प्रकार का हो सकता है। इससे हमें पहले a और फिर b फ़ीड करने में सक्षम बनाता है, और यह काम करेगा। x अब बाहर एकवचन कुछ नहीं होना चाहिए।

Monad परिभाषा में आप जो देख रहे हैं वह "ExplicitForAll" भाषा एक्सटेंशन है। इस विस्तार के लिए Haskell Prime पर एक विवरण

ExplicitForAll स्पष्ट रूप से यह है कि एक प्रकार अपनी स्वतंत्र प्रकार चर में बहुरूपी है 'forall' कीवर्ड का उपयोग सक्षम बनाता है। यह किसी भी प्रकार को लिखे जाने की अनुमति नहीं देता है जिसे पहले ही लिखा नहीं जा सकता है; यह प्रोग्रामर को स्पष्ट रूप से (वर्तमान में अंतर्निहित) मात्रा को स्पष्ट करने की अनुमति देता है।

यह भाषा विस्तार पूरी तरह से दृश्य है, जो आपको स्पष्ट रूप से वेरिएबल लिखने की अनुमति देता है जो आप पहले नहीं कर सकते थे। आप Monad घोषणा से forall a b. को छोड़ सकते हैं, और कार्यक्रम कार्यात्मक रूप से वही रहेगा।

कहें, इस एक्सटेंशन के साथ आप liftTupe को forall a b x. (x -> c x) -> (a, b) -> (c a, c b) के रूप में फिर से लिख सकते हैं। परिभाषा एक जैसी है और यह वही कार्य करती है, लेकिन पाठक अब स्पष्ट रूप से देखेंगे कि प्रकार चर सभी शीर्ष स्तर पर परिभाषित किए गए हैं।

+0

@mschmidt अच्छी पकड़, मैं जवाब का विस्तार करूंगा। – Malcolm

+0

@ थ्रीएफएक्स मैंने 'लिफ्ट टुप' के बारे में लिखा, 'लिफ्ट टुपल' नहीं। – Malcolm

+0

अरे, मेरे बुरे, मैंने सोचा कि यह एक टाइपो था! – ThreeFx

3

हास्केल के प्रकार सिस्टम में सभी प्रकार के चर forall द्वारा प्रमाणित किए जाते हैं।हालांकि, जीएचसी कई मामलों में मात्रा का अनुमान लगा सकता है ताकि आपको उन्हें स्रोत कोड में लिखने की आवश्यकता न हो।

उदाहरण के लिए forall स्पष्ट साथ liftTuple के प्रकार

liftTuple :: forall c a b. (forall x. x -> c x) -> (a, b) -> (c a, c b) 

है और >>= के लिए मामले में ही है।

5

हर समारोह आप लिखते हैं परोक्ष सार्वभौमिक अपने प्रकार चर से अधिक मात्रा निर्धारित किया जाता है:

id :: a -> a   -- this is actually universally quantified over a 
id :: forall a. a -> a 
id x = x 

आप वास्तव में ExplicitForall भाषा pragma साथ पर इस व्यवहार बदल सकते हैं।

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

बहुरूपी समारोह की सभी आवृत्तियों लागू उसी तरह व्यवहार करने के लिए, प्रकार तर्क पर ध्यान दिए बिना parametricity कहा जाता है और बार्तोज़ Milewski द्वारा this ब्लॉग पोस्ट में समझाया गया है। टीएल; डीआर है: पैरामीट्रिकिटी का उपयोग करके, हम गारंटी दे सकते हैं कि कार्यक्रम की संरचना में कुछ पुनरीक्षण इस व्यवहार को प्रभावित नहीं करते हैं। इसके गणितीय रूप से अधिक कठोर उपचार के लिए, फिलिप वाडलर द्वारा Theorems for free! देखें।

2

मोनैड परिभाषा में फोड़ा केवल सार्वभौमिक मात्रा को और स्पष्ट बनाने के लिए है। यदि आपके पास आगे प्रतिबंधों के बिना एक प्रकार परिवर्तनीय है तो यह डिफ़ॉल्ट रूप से सार्वभौमिक है, यानी कुछ भी हो सकता है।

तो देता है forall के दो का उपयोग करता है के बीच अंतर को देखो और कैसे Haskell उन्हें देख सकते हैं:

अंतर्निहित:

foo :: (x -> f x) -> a -> b -> (f a, f b) 
-- same as 
foo :: forall f x a b . (x -> f x) -> a -> b -> (f a, f b) 
-- our function is applied to a, so x is equal to a 
foo :: forall f x a b . (x ~ a) => (x -> f x) -> a -> b -> (f a, f b) 
-- our function is also applied to b, so x is equal to b 
foo :: forall f x a b . (x ~ a, x ~ b) => (x -> f x) -> a -> b -> (f a, f b) 

उह ओह, (एक्स ~ एक, एक्स ~ ख) की आवश्यकता होगी (ए ~ बी)। इसे एनोटेशन के बिना अनुमानित किया जाएगा, लेकिन चूंकि हमने स्पष्ट रूप से विभिन्न प्रकार के चर का उपयोग किया है, सब कुछ उड़ाता है। इसे हल करने के लिए हमें हमारे कार्य के भीतर polymorphic रहने के लिए एफ की जरूरत है।

मानक हैकेल इसे व्यक्त नहीं कर सकता है इसलिए हमें रैंक 2 प्रकार या रैंकटाइप की आवश्यकता होगी। इसके साथ हम लिख सकते हैं:

foo :: (forall x . x -> f x) -> a -> b -> (f a, f b) 

नोट करें कि फ़ॉल फ़ंक्शन प्रकार का हिस्सा है। इस तरह यह हमारे कार्य में polymorphic रहता है और हम इसे सब कुछ उड़ाने के बिना विभिन्न प्रकार के लिए लागू कर सकते हैं!

नोट हम भी करते हैं सकता है:

foo :: Monad m => a -> b -> (m a, m b) 
foo a b = (return a, return b) 
+1

दरअसल, आपको 'मोनाड' की आवश्यकता नहीं है, 'आवेदक' से 'शुद्ध' पर्याप्त है। और वास्तव में वास्तव में 'Pointed' भी कमजोर है। – ThreeFx

+0

अच्छा बिंदु! क्या आधिकारिक भाषा मानक में अभी भी मोनड का सुपरक्लास है? – Taren

+0

हां, मैं जीएचसी 7.8 के बाद से विश्वास करता हूं। यदि आप इसे देखना चाहते हैं तो इसे एएमपी या आवेदक-मोनाड प्रस्ताव कहा जाता है। – ThreeFx

संबंधित मुद्दे