किसी फ़ंक्शन के लिए संदर्भित प्रासंगिक पारदर्शिता, यह इंगित करती है कि आप उस फ़ंक्शन को लागू करने का परिणाम केवल उसके तर्कों के मूल्यों को देखकर निर्धारित कर सकते हैं। आप किसी भी प्रोग्रामिंग भाषा, जैसे पायथन, स्कीम, पास्कल, सी में संदर्भात्मक पारदर्शी कार्य लिख सकते हैं।
दूसरी ओर, अधिकांश भाषाओं में आप गैर-संदर्भात्मक रूप से पारदर्शी कार्य भी लिख सकते हैं। उदाहरण के लिए, यह पायथन फ़ंक्शन:
counter = 0
def foo(x):
global counter
counter += 1
return x + counter
वास्तव में पारदर्शी रूप से पारदर्शी नहीं है
foo(x) + foo(x)
तथा
2 * foo(x)
किसी भी तर्क के लिए विभिन्न मूल्यों का उत्पादन करेगा x
। इसका कारण यह है कि फ़ंक्शन वैश्विक चर का उपयोग करता है और संशोधित करता है, इसलिए प्रत्येक आह्वान का परिणाम इस बदलती स्थिति पर निर्भर करता है, न कि केवल फ़ंक्शन के तर्क पर।
हस्केल, एक विशुद्ध रूप से कार्यात्मक भाषा, अभिव्यक्ति के मूल्यांकन को कड़ाई से अलग करती है जिसमें शुद्ध कार्य लागू होते हैं और जो हमेशा संदर्भित रूप से पारदर्शी होता है, एक्शन एक्जीक्यूशन (विशेष मानों का प्रसंस्करण) से, जो कि प्रासंगिक रूप से पारदर्शी नहीं होता है, यानी एक ही क्रिया को निष्पादित करने से हर बार हो सकता है अलग परिणाम।
तो, किसी भी हास्केल फ़ंक्शन के लिए
f :: Int -> Int
और कोई भी पूर्णांक x
, यह हमेशा सच होता है
2 * (f x) == (f x) + (f x)
कार्रवाई का एक उदाहरण लाइब्रेरी फ़ंक्शन का परिणाम है getLine
:
getLine :: IO String
अभिव्यक्ति मूल्यांकन के परिणामस्वरूप, यह फ़ंक्शन (वास्तव में एक स्थिर) सबसे पहले शुद्ध प्रकार का उत्पादन करता है IO String
। इस प्रकार के मान किसी भी अन्य की तरह मान हैं: आप उन्हें पास कर सकते हैं, उन्हें डेटा संरचनाओं में डाल सकते हैं, उन्हें विशेष कार्यों का उपयोग कर रचना कर सकते हैं, और इसी तरह। उदाहरण के लिए आप क्रियाओं की सूची बना सकते हैं जैसे:
[getLine, getLine] :: [IO String]
कार्य विशेष हैं कि आप हास्केल रनटाइम को लिखकर उन्हें निष्पादित करने के लिए कह सकते हैं:
main = <some action>
इस मामले में, जब आपका हास्केल कार्यक्रम शुरू किया जाता है, तो रनटाइम उस क्रिया के माध्यम से चलता है main
और इसे निष्पादित करता है, संभवतः साइड-इफेक्ट्स का उत्पादन करता है। इसलिए, एक्शन निष्पादन संदर्भित रूप से पारदर्शी नहीं है क्योंकि एक ही एक्शन को दो बार निष्पादित करने से रनटाइम इनपुट के रूप में प्राप्त होने के आधार पर विभिन्न परिणाम उत्पन्न कर सकते हैं।
हास्केल के प्रकार प्रणाली के लिए धन्यवाद, एक कार्रवाई का उपयोग उस संदर्भ में कभी नहीं किया जा सकता है जहां एक अन्य प्रकार की अपेक्षा की जाती है, और इसके विपरीत। इसलिए, यदि आप एक स्ट्रिंग की लंबाई का पता लगाना चाहते हैं, तो आप length
फ़ंक्शन का उपयोग कर सकते हैं :
length "Hello"
5. वापस आ जाएगा। लेकिन अगर आप टर्मिनल से पढ़े गए स्ट्रिंग की लंबाई का पता लगाना चाहते हैं, तो आप नहीं लिख सकते
length (getLine)
क्योंकि आपको एक प्रकार की त्रुटि मिलती है: length
एक प्रकार की सूची (और एक स्ट्रिंग, वास्तव में, एक सूची) के इनपुट की अपेक्षा करता है, लेकिन getLine
प्रकार IO String
(एक क्रिया) का एक मूल्य है । इस प्रकार, टाइप सिस्टम यह सुनिश्चित करता है कि एक एक्शन वैल्यू जैसे getLine
(जिसका निष्पादन मूल भाषा के बाहर किया गया हो और जो गैर-संदर्भात्मक रूप से पारदर्शी हो) गैर-एक्शन मूल्य के अंदर छिपाया नहीं जा सकता है Int
।
संपादित करें
एक्साइज सवाल का जवाब देने के लिए, यहां एक छोटा हास्केल प्रोग्राम है जो कंसोल से एक लाइन पढ़ता है और इसकी लंबाई प्रिंट करता है।
main :: IO () -- The main program is an action of type IO ()
main = do
line <- getLine
putStrLn (show (length line))
मुख्य क्रिया में दो सबऑउट होते हैं जिन्हें क्रमिक रूप से निष्पादित किया जाता है:
getline
प्रकार के IO String
,
- दूसरा इसके तर्क पर
putStrLn
प्रकार के कार्य का मूल्यांकन करके बनाया गया String -> IO ()
है।
अधिक सटीक रूप से, दूसरी क्रिया द्वारा निर्मित है
line
पहली कार्रवाई द्वारा पढ़े गए मूल्य के लिए बाध्यकारी ,
- शुद्ध कार्यों का मूल्यांकन
length
(पूर्णांक के रूप में लंबाई की गणना) और फिर show
(पूर्णांक में पूर्णांक को मोड़ें),
putStrLn
के परिणाम के लिए समारोह लागू करके कार्रवाई का निर्माण show
।
इस बिंदु पर, दूसरी कार्रवाई निष्पादित की जा सकती है। यदि आपने "हैलो" टाइप किया है, तो यह "5" प्रिंट करेगा।
ध्यान दें कि यदि आपको <-
नोटेशन का उपयोग करके किसी कार्रवाई से कोई मूल्य मिलता है, तो आप केवल उस मूल्य का उपयोग किसी अन्य कार्रवाई के अंदर कर सकते हैं, जैसे कि आप नहीं लिख सकते हैं:
main = do
line <- getLine
show (length line) -- Error:
-- Expected type: IO ()
-- Actual type: String
क्योंकि show (length line)
टाइप है String
जबकि do notation के लिए आवश्यक है कि एक एक्शन ( getLine
प्रकार का IO String
) दूसरे एक्शन (उदाहरण putStrLn (show (length line))
के प्रकार IO ()
) के बाद हो।
EDIT 2
जार्ग डब्ल्यू मित्तग की संदर्भात्मक पारदर्शिता की परिभाषा मेरी तुलना में अधिक सामान्य है (मैंने उनके जवाब को गलत ठहराया है)। मैंने एक प्रतिबंधित परिभाषा का उपयोग किया है क्योंकि प्रश्न में उदाहरण कार्यों के वापसी मूल्य पर केंद्रित है और मैं इस पहलू को चित्रित करना चाहता था। हालांकि, सामान्य रूप से आरटी पूरे कार्यक्रम के अर्थ को संदर्भित करता है, जिसमें वैश्विक स्थिति में बदलाव और एक अभिव्यक्ति का मूल्यांकन करने के कारण पर्यावरण (आईओ) के साथ बातचीत शामिल है। तो, एक सही, सामान्य परिभाषा के लिए, आपको उस उत्तर का उल्लेख करना चाहिए।