कार्यात्मक प्रोग्रामिंग में एक समय फ़ंक्शन कैसे हो सकता है?


646

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

उदाहरण के लिए, इस पर विचार करें:

f(x,y) = x*x + y; // It is a mathematical function

चाहे आप कितनी भी बार उपयोग करें f(10,4), उसका मूल्य हमेशा रहेगा 104। जैसे, आपने जहां भी लिखा है f(10,4), आप इसे 104पूरे अभिव्यक्ति के मूल्य में बदलाव किए बिना बदल सकते हैं। इस संपत्ति को एक अभिव्यक्ति की संदर्भित पारदर्शिता के रूप में जाना जाता है ।

जैसा कि विकिपीडिया कहता है ( लिंक ),

इसके विपरीत, कार्यात्मक कोड में, एक फ़ंक्शन का आउटपुट मान केवल उन तर्कों पर निर्भर करता है जो फ़ंक्शन के लिए इनपुट होते हैं, इसलिए किसी फ़ंक्शन x के लिए समान मान के साथ दो बार फ़ंक्शन फ़ंक्शन कॉल करने से दोनों बार एक ही परिणाम f (x) उत्पन्न होगा।

क्या फंक्शनल प्रोग्रामिंग में एक टाइम फंक्शन (जो वर्तमान समय लौटाता है ) मौजूद हो सकता है?

  • यदि हाँ, तो इसका अस्तित्व कैसे हो सकता है? क्या यह कार्यात्मक प्रोग्रामिंग के सिद्धांत का उल्लंघन नहीं करता है? यह विशेष रूप से संदर्भात्मक पारदर्शिता का उल्लंघन करता है जो कार्यात्मक प्रोग्रामिंग की संपत्ति में से एक है (यदि मैं इसे सही ढंग से समझता हूं)।

  • या यदि नहीं, तो कोई व्यक्ति कार्यात्मक प्रोग्रामिंग में वर्तमान समय को कैसे जान सकता है?


15
मुझे लगता है कि अधिकांश (या सभी) कार्यात्मक भाषाएं इतनी सख्त नहीं हैं और कार्यात्मक और अनिवार्य प्रोग्रामिंग को जोड़ती हैं। कम से कम, यह एफ # से मेरी धारणा है।
एलेक्स एफ

13
@ एडम: पहली बार में फोन करने वाले को मौजूदा समय का पता कैसे चलेगा?
नवाज

29
@ एडम: वास्तव में यह शुद्ध रूप से कार्यात्मक भाषाओं में (जैसा कि असंभव है) अवैध है।
sepp2k

47
@ एडम: बहुत ज्यादा। एक सामान्य प्रयोजन की भाषा जो शुद्ध होती है, आमतौर पर "विश्व स्थिति" (यानी मौजूदा समय की चीजें, एक निर्देशिका में फाइलें आदि) को बिना किसी संदर्भ के पारदर्शी पारदर्शिता को तोड़ने के लिए कुछ सुविधा प्रदान करती है। हास्केल में वह IO मोनाद है और क्लीन में यह दुनिया का प्रकार है। इसलिए उन भाषाओं में एक फ़ंक्शन जिसे वर्तमान समय की आवश्यकता है या तो इसे एक तर्क के रूप में लेंगे या उसे अपने वास्तविक परिणाम (हास्केल) के बजाय एक आईओ कार्रवाई वापस करने या विश्व राज्य को अपने तर्क (क्लीन) के रूप में लेने की आवश्यकता होगी।
9

12
एफपी के बारे में सोचते समय यह भूलना आसान है: एक कंप्यूटर उत्परिवर्ती राज्य का एक बड़ा हिस्सा है। एफपी इसे बदलता नहीं है, यह केवल इसे छुपाता है।
डैनियल

जवाबों:


176

इसे समझाने का एक और तरीका यह है: कोई भी फ़ंक्शन वर्तमान समय को प्राप्त नहीं कर सकता है (क्योंकि यह बदलता रहता है), लेकिन एक क्रिया को वर्तमान समय मिल सकता है। मान लें कि getClockTimeयह एक स्थिर (या एक अशक्त कार्य है, यदि आप चाहें तो) जो वर्तमान समय को प्राप्त करने की क्रिया का प्रतिनिधित्व करता है। यह क्रिया हर बार समान होती है, जब भी इसका उपयोग किया जाता है तो यह एक वास्तविक स्थिरांक है।

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

अब, आप कंसोल को वर्तमान समय कैसे प्रिंट कर सकते हैं? ठीक है, आपको दो कार्यों को संयोजित करना होगा। तो हम ऐसा कैसे कर सकते हैं? हम सिर्फ पारित नहीं हो सकता getClockTimeकरने के लिए print, के बाद से प्रिंट एक टाइमस्टैम्प, नहीं एक कार्रवाई की उम्मीद है। लेकिन हम कल्पना कर सकते हैं कि एक ऑपरेटर है, >>=जो दो कार्यों को जोड़ता है , एक जो टाइमस्टैम्प प्राप्त करता है, और जो एक तर्क के रूप में लेता है और उसे प्रिंट करता है। पहले बताई गई क्रियाओं पर इसे लागू करते हुए, परिणाम है ... टाडा ... एक नई क्रिया जो वर्तमान समय को प्राप्त करती है और उसे प्रिंट करती है। और यह संयोग से ठीक है कि हास्केल में यह कैसे किया जाता है।

Prelude> System.Time.getClockTime >>= print
Fri Sep  2 01:13:23 東京 (標準時) 2011

तो, वैचारिक रूप से, आप इसे इस तरह से देख सकते हैं: एक शुद्ध कार्यात्मक कार्यक्रम किसी भी I / O का प्रदर्शन नहीं करता है, यह एक क्रिया को परिभाषित करता है , जिसे रनटाइम सिस्टम तब निष्पादित करता है। कार्रवाई हर बार समान है, लेकिन यह क्रियान्वित करने का परिणाम है जब यह मार डाला जाता है की परिस्थितियों पर निर्भर करता है।

मुझे नहीं पता कि यह अन्य स्पष्टीकरणों की तुलना में कोई स्पष्ट था, लेकिन यह कभी-कभी मुझे इस तरह से सोचने में मदद करता है।


33
यह मेरे लिए आश्वस्त नहीं है। आपने getClockTimeफ़ंक्शन के बजाय सुविधा से कॉल किया । ठीक है, यदि आप ऐसा कहते हैं, तो हर फ़ंक्शन कार्रवाई को कॉल करें , फिर भी अनिवार्य प्रोग्रामिंग कार्यात्मक प्रोग्रामिंग बन जाएगा। या हो सकता है, आप इसे एक्टिवा प्रोग्रामिंग कहेंगे ।
नवाज

92
@ नवाज़: यहाँ ध्यान देने योग्य बात यह है कि आप किसी कार्य को किसी फ़ंक्शन के भीतर निष्पादित नहीं कर सकते। आप केवल नए कार्यों को करने के लिए क्रियाओं और कार्यों को एक साथ जोड़ सकते हैं। किसी कार्रवाई को निष्पादित करने का एकमात्र तरीका यह है कि आप इसे अपनी mainकार्रवाई में लिखें । यह शुद्ध कार्यात्मक कोड को अनिवार्य कोड से अलग करने की अनुमति देता है, और यह पृथक्करण प्रकार प्रणाली द्वारा लागू किया जाता है। प्रथम श्रेणी की वस्तुओं के रूप में क्रियाओं का व्यवहार करना भी आपको उनके आसपास से गुजरने और अपनी खुद की "नियंत्रण संरचनाओं" का निर्माण करने की अनुमति देता है।
हमार

36
हास्केल में सब कुछ एक फ़ंक्शन है - यह पूरी तरह से बकवास है। एक फ़ंक्शन कुछ ऐसा है, जिसके प्रकार में एक है ->- यह है कि मानक शब्द को कैसे परिभाषित करता है और यह वास्तव में हास्केल के संदर्भ में एकमात्र समझदार परिभाषा है। कुछ जिसका प्रकार है तो IO Whateverहै नहीं एक समारोह।
10

9
@ sepp2k तो, myList :: [a -> b] एक फंक्शन है? ;)
फज

8
@ThomasEding मैं वास्तव में पार्टी के लिए देर हो चुकी हूं, लेकिन मैं सिर्फ यह स्पष्ट करना चाहता हूं: putStrLnयह एक कार्रवाई नहीं है - यह एक फ़ंक्शन है जो एक कार्रवाई देता है। getLineएक चर है जिसमें एक क्रिया होती है। क्रियाएँ मूल्य, चर और कार्य "कंटेनर" / "लेबल" हैं जो हम उन कार्यों को देते हैं।
kqr

356

हां और ना।

विभिन्न कार्यात्मक प्रोग्रामिंग भाषाएं उन्हें अलग तरीके से हल करती हैं।

हास्केल (एक बहुत ही शुद्ध) में यह सब सामान I / O मोनाड नामक चीज़ में होता है - यहाँ देखें ।

आप इसे अपने कार्य (विश्व-राज्य) में एक और इनपुट (और आउटपुट) प्राप्त करने के रूप में सोच सकते हैं या एक जगह के रूप में आसान कर सकते हैं जहां "अशुद्धता" जैसे बदलते समय को प्राप्त करना होता है।

अन्य भाषाओं जैसे F # में कुछ अशुद्धता है, और इसलिए आपके पास एक फ़ंक्शन हो सकता है जो एक ही इनपुट के लिए अलग-अलग मान लौटाता है - जैसे सामान्य अनिवार्यता वाली भाषाएँ।

जैसा कि जेफरी बुर्का ने अपनी टिप्पणी में उल्लेख किया है: यहाँ हास्केल विकी से सीधे I / O मोनाड का अच्छा परिचय है


223
हास्केल में IO मोनाड के बारे में महसूस करने के लिए महत्वपूर्ण बात यह है कि यह इस समस्या के आसपास पहुंचने के लिए सिर्फ एक हैक नहीं है; कुछ संदर्भों में क्रियाओं के अनुक्रम को परिभाषित करने की समस्या के लिए एक सामान्य समाधान है। एक संभावित संदर्भ वास्तविक दुनिया है, जिसके लिए हमारे पास आईओ मोनाद है। एक अन्य संदर्भ परमाणु लेनदेन के भीतर है, जिसके लिए हमारे पास एसटीएम मोनाड है। फिर भी एक अन्य संदर्भ एक शुद्ध कार्य के रूप में एक प्रक्रियात्मक एल्गोरिथ्म (जैसे नथ शफल) के कार्यान्वयन में है, जिसके लिए हमारे पास एसटी सनद है। और आप अपने स्वयं के भिक्षुओं को भी परिभाषित कर सकते हैं। मोनाड एक तरह का ओवरलोडेबल अर्धविराम है।
पॉल जॉनसन

2
मुझे वर्तमान समय के "फ़ंक्शंस" जैसी चीज़ों को न कहने के लिए उपयोगी लगता है, लेकिन "प्रक्रियाएं" जैसी कुछ (हालांकि यकीनन हास्केल समाधान इसका अपवाद है)।
सिंगापोलिम्मा

हास्केल परिप्रेक्ष्य शास्त्रीय "प्रक्रियाओं" ('... -> ()') के प्रकारों के साथ एक शुद्ध कार्य के रूप में कुछ तुच्छ हैं ... -> () कुछ भी नहीं कर सकते हैं।
कार्स्टन

3
ठेठ हास्केल शब्द "एक्शन" है।
सेबेस्टियन रेडल

6
"मोनाड्स एक तरह का ओवरलोडेबल अर्धविराम है।" +1
user2805751

147

हास्केल में एक साइड इफेक्ट्स को संभालने के लिए मोनाड नामक निर्माण का उपयोग करता है । मूल रूप से एक मोनाड का अर्थ है कि आप एक कंटेनर में मूल्यों को एनकैप्सुलेट करते हैं और कुछ कार्यों को एक कंटेनर के अंदर मानों से श्रृंखला कार्य करते हैं। यदि हमारे कंटेनर में प्रकार है:

data IO a = IO (RealWorld -> (a,RealWorld))

हम सुरक्षित रूप से IO क्रियाओं को कार्यान्वित कर सकते हैं। इस प्रकार का अर्थ है: प्रकार की एक क्रिया IOएक फ़ंक्शन है, जो टाइप का टोकन लेता है RealWorldऔर परिणाम के साथ एक नया टोकन देता है।

इसके पीछे विचार यह है कि प्रत्येक IO कार्रवाई बाहरी राज्य को बदल देती है, जो जादुई टोकन द्वारा दर्शाया जाता है RealWorld। मठों का उपयोग करके, कई ऐसे कार्यों को श्रृंखलाबद्ध कर सकते हैं जो वास्तविक दुनिया को एक साथ जोड़ते हैं। संन्यासी का सबसे महत्वपूर्ण कार्य है >>=, स्पष्ट बाँध :

(>>=) :: IO a -> (a -> IO b) -> IO b

>>=एक क्रिया और एक फ़ंक्शन लेता है जो इस क्रिया का परिणाम लेता है और इसमें से एक नई क्रिया बनाता है। वापसी प्रकार नई क्रिया है। उदाहरण के लिए, आइए दिखाते हैं कि एक फ़ंक्शन है now :: IO String, जो मौजूदा समय का प्रतिनिधित्व करते हुए एक स्ट्रिंग देता है। हम इसे putStrLnप्रिंट करने के लिए फ़ंक्शन के साथ चेन कर सकते हैं:

now >>= putStrLn

या do-नोटेशन में लिखा गया है , जो एक अनिवार्य प्रोग्रामर के लिए अधिक परिचित है:

do currTime <- now
   putStrLn currTime

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


3
-1: मैं RealWorldस्मोक स्क्रीन से नाखुश हूं । फिर भी, सबसे महत्वपूर्ण बात यह है कि इस कथित वस्तु को एक श्रृंखला में कैसे पारित किया जाता है। लापता टुकड़ा वह है जहां यह शुरू होता है, जहां वास्तविक दुनिया का स्रोत या कनेक्शन है - यह मुख्य कार्य के साथ शुरू होता है जो इयाना मोनाड में चलता है।
u0b34a0f6ae

2
@ kaizer.se आप एक वैश्विक RealWorldवस्तु के बारे में सोच सकते हैं जो कार्यक्रम में शुरू होने पर पारित हो जाती है।
फज

6
मूल रूप से, आपका mainफ़ंक्शन एक RealWorldतर्क लेता है । केवल निष्पादन पर ही इसे पारित किया जाता है।
लुई वासरमैन

13
आप देखते हैं, जिस कारण वे छिपते हैं RealWorldऔर केवल उसे बदलने के लिए दंडात्मक कार्य प्रदान करते हैं putStrLn, जैसे कि कुछ हास्केल प्रोग्रामर RealWorldअपने एक कार्यक्रम के साथ नहीं बदलते हैं, जैसे हास्केल करी का पता और जन्मतिथि ऐसी है कि वे अगले दरवाजे पड़ोसी बन जाते हैं बड़े हो रहे हैं (यह हास्केल प्रोग्रामिंग भाषा को चोट पहुंचाने के लिए इस तरह से समय-स्थान की निरंतरता को नुकसान पहुंचा सकता है।)
PyRulez

2
RealWorld -> (a, RealWorld) संक्षिप्तता के तहत भी रूपक के रूप में नहीं टूटता है, जब तक आप यह ध्यान रखते हैं कि वास्तविक दुनिया ब्रह्मांड के अन्य भागों द्वारा आपके फ़ंक्शन (या आपकी वर्तमान प्रक्रिया) के बाहर हर समय बदल सकती है। इसलिए (ए) मेथफोर टूट नहीं जाता है, और (बी) हर बार एक मूल्य जो RealWorldइसके प्रकार के रूप में एक फ़ंक्शन को दिया जाता है, फ़ंक्शन का पुनर्मूल्यांकन किया जाना है, क्योंकि इस बीच वास्तविक दुनिया बदल गई होगी ( जैसा कि @fuz ने बताया है, जब हम वास्तविक दुनिया के साथ बातचीत करते हैं तो हर बार एक अलग 'टोकन मूल्य' देते हैं।
Qqwy

73

अधिकांश कार्यात्मक प्रोग्रामिंग भाषाएं शुद्ध नहीं हैं, अर्थात वे कार्यों को न केवल उनके मूल्यों पर निर्भर करने की अनुमति देती हैं। उन भाषाओं में यह संभव है कि किसी फ़ंक्शन का वर्तमान समय लौट रहा हो। जिन भाषाओं से आपने इस प्रश्न को टैग किया है, उन पर Scala और F # (साथ ही साथ ML के अन्य संस्करण ) लागू होते हैं।

हास्केल और क्लीन जैसी भाषाओं में , जो शुद्ध हैं, स्थिति अलग है। हास्केल में वर्तमान समय एक फ़ंक्शन के माध्यम से उपलब्ध नहीं होगा, लेकिन एक तथाकथित IO कार्रवाई, जो हास्केल के साइड इफेक्ट्स को रोकने का तरीका है।

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


2
इससे ऐसा लगता है जैसे हास्केल और क्लीन अलग-अलग चीजें करते हैं। जो मैं समझता हूं, वे वही करते हैं, बस इसे पूरा करने के लिए हास्केल एक अच्छे सिंटैक्स (?) की पेशकश करता है।
कोनराड रुडोल्फ

27
@ कोनराड: वे इस अर्थ में एक ही काम करते हैं कि दोनों प्रकार के सिस्टम सुविधाओं का उपयोग साइड इफेक्ट्स के लिए करते हैं, लेकिन यह इसके बारे में है। ध्यान दें कि एक विश्व प्रकार के संदर्भ में IO मोनाद की व्याख्या करना बहुत अच्छा है, लेकिन हास्केल मानक वास्तव में एक विश्व प्रकार को परिभाषित नहीं करता है और वास्तव में हैस्केल में विश्व प्रकार का मूल्य प्राप्त करना संभव नहीं है (जबकि यह बहुत संभव है और वास्तव में है साफ में आवश्यक)। आगे हास्केल में एक प्रकार की प्रणाली विशेषता के रूप में विशिष्टता टाइपिंग नहीं है, इसलिए यदि यह आपको किसी विश्व तक पहुंच प्रदान करता है, तो यह सुनिश्चित नहीं कर सकता है कि आप इसे शुद्ध तरीके से उपयोग करते हैं जिस तरह से स्वच्छ करता है।
sepp2k

51

"वर्तमान समय" एक फ़ंक्शन नहीं है। यह एक पैरामीटर है। यदि आपका कोड वर्तमान समय पर निर्भर करता है, तो इसका मतलब है कि आपका कोड समय के अनुसार परिचालित है।


22

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

C # में आप इसे इस तरह लागू कर सकते हैं:

// Exposes mutable time as immutable time (poorly, to illustrate by example)
// Although the insides are mutable, the exposed surface is immutable.
public class ClockStamp {
    public static readonly ClockStamp ProgramStartTime = new ClockStamp();
    public readonly DateTime Time;
    private ClockStamp _next;

    private ClockStamp() {
        this.Time = DateTime.Now;
    }
    public ClockStamp NextMeasurement() {
        if (this._next == null) this._next = new ClockStamp();
        return this._next;
    }
}

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

यह 'क्लॉकस्टैम्प' वर्ग एक अपरिवर्तनीय लिंक्ड सूची की तरह काम करता है, लेकिन वास्तव में नोड्स मांग पर उत्पन्न होते हैं, इसलिए वे 'वर्तमान' समय को शामिल कर सकते हैं। कोई भी फ़ंक्शन जो समय को मापना चाहता है, उसके पास एक 'क्लॉकस्टैम्प' पैरामीटर होना चाहिए और इसके परिणाम में अपना अंतिम समय माप भी वापस करना चाहिए (इसलिए कॉलर पुराने माप नहीं देखता), इस तरह:

// Immutable. A result accompanied by a clockstamp
public struct TimeStampedValue<T> {
    public readonly ClockStamp Time;
    public readonly T Value;
    public TimeStampedValue(ClockStamp time, T value) {
        this.Time = time;
        this.Value = value;
    }
}

// Times an empty loop.
public static TimeStampedValue<TimeSpan> TimeALoop(ClockStamp lastMeasurement) {
    var start = lastMeasurement.NextMeasurement();
    for (var i = 0; i < 10000000; i++) {
    }
    var end = start.NextMeasurement();
    var duration = end.Time - start.Time;
    return new TimeStampedValue<TimeSpan>(end, duration);
}

public static void Main(String[] args) {
    var clock = ClockStamp.ProgramStartTime;
    var r = TimeALoop(clock);
    var duration = r.Value; //the result
    clock = r.Time; //must now use returned clock, to avoid seeing old measurements
}

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


दिलचस्प है, लेकिन i++इसके लिए लूप में
संदर्भात्मक रूप से

@ snim2 मैं परफेक्ट नहीं हूं। : पी इस तथ्य में सांत्वना लें कि गंदे उत्परिवर्तन परिणाम के प्रासंगिक पारदर्शिता को प्रभावित नहीं करता है। यदि आप दो बार एक ही 'अंतिम निबंधन' पास करते हैं, तो आपको बासी अगला माप मिलता है और उसी परिणाम को वापस करता है।
क्रेग गिदनी

@Strilanc इसके लिए धन्यवाद। मुझे लगता है कि जरूरी कोड में है, इसलिए यह देखना दिलचस्प है कि कार्यात्मक अवधारणाएं इस तरह से बताई गई हैं। मैं तब एक ऐसी भाषा की कल्पना कर सकता हूँ जहाँ यह प्राकृतिक और कृत्रिम रूप से क्लीनर हो।
डब्ल्यूडब्ल्यू।

आप वास्तव में C # में भी मोनड तरीका अपना सकते हैं, इस प्रकार समय टिकटों के स्पष्ट पारित होने से बच सकते हैं। आपको ऐसा कुछ चाहिए struct TimeKleisli<Arg, Res> { private delegate Res(TimeStampedValue<Arg>); }। लेकिन इस के साथ कोड अभी भी doवाक्य रचना के साथ हास्केल जितना अच्छा नहीं लगेगा ।
११ बजे

@leftaroundabout आप एक # विधि के रूप में बाइंड फ़ंक्शन को लागू करके C # में एक मोनाड का दिखावा कर सकते हैं SelectMany, जो क्वेरी कंप्रीहेंशन सिंटैक्स को सक्षम करता है। आप अभी भी भिक्षुओं पर बहुरूपिया कार्यक्रम नहीं कर सकते हैं, इसलिए यह कमजोर प्रकार की प्रणाली के खिलाफ एक कठिन लड़ाई है :(
सारा

16

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

यह प्रतिक्रियाशील कार्यात्मक प्रोग्रामिंग में एक गर्म विषय है। यदि आप इस तरह के सामान में रुचि रखते हैं, तो इसे पढ़ें: http://digitalcommons.ohsu.edu/csetech/91/ (28 पीपी।)


3
और यह कैसे इस प्रश्न से संबंधित है?
नवाज

5
आपका सवाल शुद्ध रूप से कार्यात्मक तरीके से समय-निर्भर व्यवहार के बारे में था, उदाहरण के लिए, एक फ़ंक्शन जो वर्तमान सिस्टम घड़ी लौटाता है। आप या तो उस स्थिति तक पहुँचने के लिए सभी कार्यों और उनकी निर्भरता के पेड़ के माध्यम से एक IO मोनाड के बराबर कुछ धागा कर सकते हैं; या आप रचनात्मक नियमों के बजाय अवलोकन नियमों को परिभाषित करके राज्य को मॉडल कर सकते हैं। यही कारण है कि जटिल राज्य मॉडलिंग है उपपादन द्वारा कार्यात्मक प्रोग्रामिंग में तो अप्राकृतिक लगता है, क्योंकि छिपा राज्य वास्तव में एक है coinductive संपत्ति।
जेफरी एगुइलेरा

महान स्रोत! क्या हाल ही में कुछ हुआ है? जेएस समुदाय अभी भी धारा डेटा सार के साथ संघर्ष कर रहा है।
दिमित्री जैतसेव

12

हां, शुद्ध कार्य के लिए समय लौटाना संभव है, यदि यह उस समय को पैरामीटर के रूप में दिया गया हो। अलग समय तर्क, अलग समय परिणाम। फिर समय के अन्य कार्यों के रूप में अच्छी तरह से बनाते हैं और उन्हें फ़ंक्शन (-of-time) -transforming (उच्च-क्रम) कार्यों की एक सरल शब्दावली के साथ जोड़ते हैं। चूंकि दृष्टिकोण राज्यविहीन है, यहाँ समय बल्कि असतत से निरंतर (संकल्प-स्वतंत्र) हो सकता है, बहुत प्रतिरूपकता बढ़ाने । यह अंतर्ज्ञान कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग (एफआरपी) का आधार है।


11

हाँ! तुम सही हो! अब () या करंटटाइम () या इस तरह के स्वाद के किसी भी तरीके के हस्ताक्षर एक तरह से संदर्भात्मक पारदर्शिता का प्रदर्शन नहीं कर रहे हैं। लेकिन संकलक को निर्देश द्वारा यह एक सिस्टम क्लॉक इनपुट द्वारा मानकीकृत है।

आउटपुट के अनुसार, अब () संदर्भात्मक पारदर्शिता का पालन नहीं कर सकता है। लेकिन सिस्टम क्लॉक और उसके शीर्ष पर फ़ंक्शन का वास्तविक व्यवहार रेफरेन्शियल ट्रांसपेरेंसी का पालन करता है।


11

हां, एक समय मिलने वाला कार्य कार्यात्मक प्रोग्रामिंग में थोड़ा संशोधित संस्करण का उपयोग करके कार्यात्मक प्रोग्रामिंग में मौजूद हो सकता है, जिसे अशुद्ध कार्यात्मक प्रोग्रामिंग के रूप में जाना जाता है (डिफ़ॉल्ट या मुख्य एक शुद्ध कार्यात्मक प्रोग्रामिंग है)।

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

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

इसे देखने का एक और दिलचस्प तरीका यह होगा कि फ़ंक्शनल प्रोग्रामिंग में आपका समय मिलने वाला कार्य एक "विश्व" ऑब्जेक्ट लेगा, जिसमें दुनिया की वर्तमान स्थिति होती है जैसे समय, दुनिया में रहने वाले लोगों की संख्या आदि, फिर किस दुनिया से समय वस्तु हमेशा शुद्ध होगी अर्थात आप उसी विश्व अवस्था में गुजरेंगे जहाँ आपको हमेशा समान समय मिलेगा।


1
"सभी सॉफ्टवेयर के बाद जो बाहरी दुनिया के साथ बातचीत नहीं करता है, कुछ गणितीय संगणना करने के अलावा कोई उपयोगी नहीं है।" जहां तक ​​मैं समझता हूं, इस मामले में भी संगणनाओं के इनपुट को प्रोग्राम में हार्ड-कोड किया जाएगा, यह भी बहुत उपयोगी नहीं है। जैसे ही आप फ़ाइल या टर्मिनल से अपने गणितीय अभिकलन में इनपुट डेटा पढ़ना चाहते हैं, आपको अशुद्ध कोड की आवश्यकता होती है।
जियोर्जियो

1
@Ankur: वही सटीक बात है। यदि कार्यक्रम केवल स्वयं के अलावा किसी अन्य चीज़ के साथ बातचीत कर रहा है (उदाहरण के लिए वे कीबोर्ड के माध्यम से दुनिया, तो बोलने के लिए) यह अभी भी अशुद्ध है।
पहचान

1
@ ठाकुर: हाँ, मुझे लगता है कि तुम सही हो! भले ही यह कमांड लाइन पर बड़े इनपुट डेटा को पारित करने के लिए बहुत व्यावहारिक नहीं है, लेकिन यह इसे करने का एक शुद्ध तरीका हो सकता है।
जियोर्जियो

2
दुनिया में रहने वाले लोगों की संख्या सहित "विश्व वस्तु" होने से निष्पादन कंप्यूटर को निकट सर्वज्ञ स्तर तक बढ़ा दिया जाता है। मुझे लगता है कि सामान्य मामला यह है कि इसमें ऐसी चीजें शामिल हैं जैसे आपके HD पर कितनी फाइलें हैं और वर्तमान उपयोगकर्ता की होम डायरेक्टरी क्या है।
जिग्गीस्टार

4
@ जिग्गीस्टार - "वर्ल्ड ऑब्जेक्ट" में वास्तव में कुछ भी शामिल नहीं है - यह प्रोग्राम के बाहर दुनिया की बदलती स्थिति के लिए बस एक प्रॉक्सी है। इसका एकमात्र उद्देश्य एक तरह से उत्परिवर्तनीय स्थिति को स्पष्ट रूप से चिह्नित करना है जिससे कि प्रकार प्रणाली इसकी पहचान कर सके।
क्रिश न्यूटीकॉम्बे

7

आपका प्रश्न एक कंप्यूटर भाषा के दो संबंधित उपायों को बताता है: कार्यात्मक / अनिवार्य और शुद्ध / अशुद्ध।

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

शुद्ध भाषा साइड इफेक्ट्स का निर्माण या निर्भर नहीं करती है, और एक अशुद्ध भाषा उनका उपयोग करती है।

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

सभी के लिए उपयोगी होने के लिए, एक कार्यक्रम में कम से कम एक फ्रिज अशुद्ध होना चाहिए। एक शुद्ध कार्यक्रम को उपयोगी बनाने का एक तरीका यह है कि इसे एक पतली अशुद्ध आवरण के अंदर रखा जाए। इस अनुपयोगी हास्केल कार्यक्रम की तरह:

-- this is a pure function, written in functional style.
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)

-- This is an impure wrapper around the pure function, written in imperative style
-- It depends on inputs and produces outputs.
main = do
    putStrLn "Please enter the input parameter"
    inputStr <- readLine
    putStrLn "Starting time:"
    getCurrentTime >>= print
    let inputInt = read inputStr    -- this line is pure
    let result = fib inputInt       -- this is also pure
    putStrLn "Result:"
    print result
    putStrLn "Ending time:"
    getCurrentTime >>= print

4
यदि आप समय प्राप्त करने के विशिष्ट मुद्दे को संबोधित कर सकते हैं, तो यह मददगार होगा और हमने IOमूल्यों और परिणामों को शुद्ध मानने के लिए किस सीमा तक विचार किया ।
एंड्रयूसी

वास्तव में, यहां तक ​​कि 100% शुद्ध कार्यक्रम सीपीयू को गर्म करते हैं, जो एक साइड-इफेक्ट है।
जॉर्ग डब्ल्यू मित्तग

3

आप कार्यात्मक प्रोग्रामिंग में एक बहुत ही महत्वपूर्ण विषय पर प्रशिक्षण दे रहे हैं, अर्थात I / O का प्रदर्शन कर रहे हैं। जिस तरह से कई शुद्ध भाषाओं के बारे में जाना जाता है वह एम्बेडेड डोमेन-विशिष्ट भाषाओं का उपयोग करके होता है, उदाहरण के लिए, एक sublanguage जिसका कार्य कार्यों को एनकोड करना है , जिसके परिणाम हो सकते हैं।

उदाहरण के लिए हास्केल रनटाइम मुझे उम्मीद mainकरता है कि एक एक्शन को परिभाषित किया जाए जो कि मेरे प्रोग्राम को बनाने वाली सभी क्रियाओं से बना है। रनटाइम तब इस क्रिया को निष्पादित करता है। ज्यादातर समय, ऐसा करने में यह शुद्ध कोड निष्पादित करता है। समय-समय पर रनटाइम गणना किए गए डेटा का उपयोग I / O करने के लिए करेगा और डेटा को वापस शुद्ध कोड में फीड करेगा।

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

उदाहरण: clock_t c = time(NULL); printf("%d\n", c + 2);C में, बनाम main = getCPUTime >>= \c -> print (c + 2*1000*1000*1000*1000)हास्केल में। ऑपरेटर >>=का उपयोग क्रियाओं की रचना करने के लिए किया जाता है, पहली के परिणाम को एक समारोह में पारित करने के परिणामस्वरूप दूसरी क्रिया के परिणामस्वरूप। यह काफी आर्कषक लग रहा है, हास्केल संकलक सिन्थेटिक चीनी का समर्थन करता है जो हमें बाद के कोड को निम्न प्रकार से लिखने की अनुमति देता है:

type Clock = Integer -- To make it more similar to the C code

-- An action that returns nothing, but might do something
main :: IO ()
main = do
    -- An action that returns an Integer, which we view as CPU Clock values
    c <- getCPUTime :: IO Clock
    -- An action that prints data, but returns nothing
    print (c + 2*1000*1000*1000*1000) :: IO ()

उत्तरार्द्ध काफी जरूरी लग रहा है, है ना?


1

यदि हाँ, तो इसका अस्तित्व कैसे हो सकता है? क्या यह कार्यात्मक प्रोग्रामिंग के सिद्धांत का उल्लंघन नहीं करता है? यह विशेष रूप से संदर्भात्मक पारदर्शिता का उल्लंघन करता है

यह विशुद्ध रूप से कार्यात्मक अर्थों में मौजूद नहीं है।

या यदि नहीं, तो कोई व्यक्ति कार्यात्मक प्रोग्रामिंग में वर्तमान समय को कैसे जान सकता है?

कंप्यूटर पर किसी समय को कैसे पुनर्प्राप्त किया जाता है, यह जानना सबसे पहले उपयोगी हो सकता है। अनिवार्य रूप से ऑनबोर्ड सर्किट्री है जो समय का ट्रैक रखता है (जो कि एक कारण है कि कंप्यूटर को आमतौर पर एक छोटी सेल बैटरी की आवश्यकता होगी)। फिर कुछ आंतरिक प्रक्रिया हो सकती है जो एक निश्चित मेमोरी रजिस्टर में समय का मूल्य निर्धारित करती है। जो अनिवार्य रूप से एक मूल्य पर उबलता है जिसे सीपीयू द्वारा पुनर्प्राप्त किया जा सकता है।


हास्केल के लिए, एक 'IO क्रिया' की एक अवधारणा है जो एक प्रकार का प्रतिनिधित्व करती है जिसे कुछ IO प्रक्रिया को पूरा करने के लिए बनाया जा सकता है। इसलिए एक timeमूल्य को संदर्भित करने के बजाय हम एक मूल्य का संदर्भ देते हैं IO Time। यह सब विशुद्ध रूप से कार्यात्मक होगा। हम संदर्भित नहीं कर रहे हैं, timeलेकिन 'समय रजिस्टर का मूल्य पढ़ें' की तर्ज पर कुछ ।

जब हम वास्तव में हास्केल कार्यक्रम को कार्यान्वित करते हैं, तो IO कार्रवाई वास्तव में होगी।

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