scala - कार्यात्मक प्रोग्रामिंग में समय कार्य कैसे हो सकता है?




haskell f# (9)

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

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

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

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

विकिपीडिया कहता है ( link )

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

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

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

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


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

यह पूरी तरह कार्यात्मक भावना में मौजूद नहीं है।

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

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

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

जब हम वास्तव में हास्केल प्रोग्राम निष्पादित करते हैं, तो आईओ कार्रवाई वास्तव में होती है।


"वर्तमान समय" एक समारोह नहीं है। यह एक पैरामीटर है। यदि आपका कोड वर्तमान समय पर निर्भर करता है, तो इसका मतलब है कि आपका कोड समय के साथ पैरामीटरकृत है।


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

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

उदाहरण: clock_t c = time(NULL); printf("%d\n", c + 2); clock_t c = time(NULL); printf("%d\n", c + 2); सी में, बनाम 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 ()

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


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

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

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

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

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

-- 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

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

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


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

सी # में आप इसे इस तरह कार्यान्वित कर सकते हैं:

// 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
}

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


हां और ना।

विभिन्न एफपी भाषाएं उन्हें अलग-अलग हल करती हैं।

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

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

जैसा कि जेफरी बुर्का ने अपनी टिप्पणी में उल्लेख किया है: आईओ मोनाड के लिए सीधे हास्केलविकि से अच्छा intro है।


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


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

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

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

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

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

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

now >>= putStrLn

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

do currTime <- now
   putStrLn currTime

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





clean-language