2010-10-30 11 views
6

कृपया मेरे साथ भालू क्योंकि मैं कार्यात्मक प्रोग्रामिंग और हास्केल के लिए बहुत नया हूं। मैं हास्केल में एक फ़ंक्शन लिखने का प्रयास कर रहा हूं जो इंटेगर्स की एक सूची लेता है, कहा गया सूची के प्रमुख को प्रिंट करता है, और फिर सूची की पूंछ देता है। फ़ंक्शन को प्रकार [इंटीजर] -> [इंटीजर] होना चाहिए। थोड़ा सा संदर्भ देने के लिए, मैं एक दुभाषिया लिख ​​रहा हूं और इस फ़ंक्शन को तब कहा जाता है जब उसके संबंधित कमांड को एक सहयोगी सूची में देखा जाता है (कुंजी कमांड है, मान फ़ंक्शन है)।हास्केल: I/O और एक फ़ंक्शन से लौटने

forth.hs:12:1: 
Couldn't match expected type `[a]' against inferred type `IO [a]' 
    Expected type: ([Char], [a] -> [a]) 
    Inferred type: ([Char], [a] -> IO [a]) 
In the expression: (".", dot) 

मुझे लगता है कि कॉल डॉट समारोह में मुद्रित करने के लिए क्या हो रहा है है:

dot (x:xs) = do print x 
     return xs 

संकलक निम्न त्रुटि संदेश देता है:

यहाँ कोड मैं लिखा है है अनुमानित प्रकार आईओ [ए] होना चाहिए। क्या कोई तरीका है कि मैं रिटर्न प्रकार के प्रिंट को अनदेखा कर सकता हूं, क्योंकि मुझे वापस लौटने की ज़रूरत है, सूची की पूंछ डॉट में पारित की जा रही है।

अग्रिम धन्यवाद।

उत्तर

8

अधिकांश कार्यात्मक भाषाओं में, यह काम करेगा। हालांकि, हास्केल शुद्ध कार्यात्मक भाषा है। आप कार्यों में आईओ करने के लिए अनुमति नहीं है, इसलिए समारोह या तो आईओ

dot के प्रकार के रूप में संकलक द्वारा लगाए गए अनुमान है के साथ किसी भी IO या

  • [Int] -> IO [Int] बिना प्रदर्शन

    1. [Int] -> [Int] हो सकता है dot :: (Show t) => [t] -> IO [t] लेकिन आप इसे घोषणा कर सकते हैं [Int] -> IO [Int] होने के लिए:

      dot :: [Int] -> IO [Int]

      ,210

      आईओ देखें इकाई: http://book.realworldhaskell.org/read/io.html


      मैं System.IO.Unsafe.unsafePerformIO कि बड़ी सावधानी से और उसके परिणामों की एक फर्म समझ के साथ प्रयोग किया जाना चाहिए उल्लेख नहीं किया है।

  • +3

    [ 'Debug.Trace'] (http: // www .haskell.org/ghc/docs/6.12.2/html/पुस्तकालय/आधार-4.2.0.1/डीबग-Trace.html) मॉड्यूल का उपयोग चीजों को मुद्रित करने के लिए भी किया जा सकता है। –

    8

    नहीं, या तो आपका कार्य दुष्प्रभाव का कारण बनता है (उर्फ आईओ, इस मामले में स्क्रीन पर प्रिंटिंग), या ऐसा नहीं है। print आईओ करता है और इसलिए IO में कुछ देता है और इसे पूर्ववत नहीं किया जा सकता है।

    और यह एक बुरी बात होगी यदि संकलक को IO के बारे में भूलने में धोखा दिया जा सकता है। उदाहरण के लिए यदि आपके [Integer] -> [Integer] फ़ंक्शन को आपके प्रोग्राम में कई पैरामीटर (जैसे [] उदाहरण के लिए) कहा जाता है, तो संकलक पूरी तरह से केवल एक बार फ़ंक्शन निष्पादित कर सकता है और उस स्थान के सभी स्थानों पर इसका परिणाम उपयोग कर सकता है जहां फ़ंक्शन " बुलाया"। आपका "छुपा" प्रिंट केवल एक बार निष्पादित किया जाएगा भले ही आपने कई स्थानों पर फ़ंक्शन को बुलाया हो।

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

    5

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

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

    हैक्स का उपयोग किए बिना, इसका मतलब है कि आपको अपनी आईओ क्रियाएं main फ़ंक्शन पर वापस लेनी होगी। व्यावहारिक रूप से बोलते हुए, इसका मतलब है कि main और dot के बीच सबकुछ "आईओ मोनाड" में होना चाहिए। "आईओ मोनाद" में क्या होता है, इसलिए "आईओ मोनाद" में बात करने के लिए रहता है।

    संपादित

    यहाँ सबसे सरल उदाहरण मैं एक वैध हास्केल प्रोग्राम में अपने dot समारोह का उपयोग करने के बारे में कल्पना कर सकता है:

    module Main where 
    
    main :: IO() 
    main = 
        do 
         let xs = [2,3,4] 
         xr <- dot xs 
         xrr <- dot xr 
         return() 
    
    dot (x:xs) = 
        do 
         print x 
         return xs 
    
    संबंधित मुद्दे