2009-11-04 10 views
31

मैंने टेक्स्ट की अनुक्रमणिका बनाने के लिए हास्केल में कोड का एक गुच्छा लिखा था। शीर्ष समारोह इस तरह दिखता है:प्रकार का एक हास्केल फ़ंक्शन: आईओ स्ट्रिंग-> स्ट्रिंग

index :: String -> [(String, [Integer])] 
index a = [...] 

अब मैं इस समारोह एक स्ट्रिंग एक फ़ाइल से पढ़ने देना चाहता हूँ:

index readFile "input.txt" 

कौन सा काम नहीं करेगा क्योंकि readfile प्रकार FilePath की है -> आईओ स्ट्रिंग ।

की उम्मीद नहीं मेल खा सकते हैं प्रकार 'स्ट्रिंग' अनुमानित प्रकार के खिलाफ 'आईओ स्ट्रिंग'

मैं त्रुटि देखते हैं, लेकिन मैं प्रकार के साथ किसी भी समारोह नहीं मिल सकता है:

IO String -> String 

मुझे लगता है कि सफलता की कुंजी कुछ मोनाड्स के नीचे कहीं स्थित है, लेकिन मुझे अपनी समस्या का समाधान करने का कोई तरीका नहीं मिला।

+3

एक अच्छा इकाई ट्यूटोरियल के लिए यहाँ एक नजर डालें इकाई functors के पर गौर कर सकते हैं: http://blog.sigfpe.com/2006/ 08/आप-हो सकता है-आविष्कार-monads-and.html –

+1

अन्य अच्छे संसाधन यहां SO में पाए जा सकते हैं। बस अपनी स्क्रीन पर संबंधित अनुभाग देखें, दाएं-नीचे। –

उत्तर

37

आप आसानी से एक फ़ंक्शन लिख सकते हैं जो readFile कार्रवाई को कॉल करता है, और परिणाम को आपके इंडेक्स फ़ंक्शन में पास करता है।

readAndIndex fileName = do 
    text <- readFile fileName 
    return $ index text 

हालांकि, आईओ इकाई सब कुछ यह का उपयोग करता है taints, इसलिए इस समारोह प्रकार का है:

readAndIndex :: FilePath -> IO [(String, [Integer])] 
+3

यह सिर्फ एक छोटी सी वाक्य है: "आईओ मोनैड सबकुछ बताता है जो इसका उपयोग करता है"। मुझे लगता है कि यह मामला था, लेकिन अब यह पुष्टि करना अच्छा लगता है। धन्यवाद ^^ – drumfire

15

ठीक है आप IO String के मोनड भाग से छुटकारा नहीं पा सकते हैं। इसका मतलब है कि आपको अपना फ़ंक्शन IO [(String, [Integer])] वापस करना होगा।

मैं monads बारे में अधिक जानने की सलाह देते हैं, लेकिन अब आप liftM समारोह के साथ भाग प्राप्त कर सकते हैं:

liftM index (readFile "input.txt") 

liftM इस हस्ताक्षर है:

liftM :: Monad m => (a -> b) -> m a -> m b 

यह एक गैर monadic समारोह लेता है और इसे एक monadic समारोह में बदल देता है।

27

वहाँ एक बहुत अच्छा कारण है कि इस तरह का कोई समारोह है वहाँ है।

हास्केल में कार्यात्मक शुद्धता की धारणा है। इसका मतलब यह है कि एक ही पैरामीटर के साथ बुलाए जाने पर एक फ़ंक्शन हमेशा एक ही परिणाम देगा। केवल स्थान जहां आईओ की अनुमति है IO monad के अंदर है।

अगर वहाँ एक समारोह

index :: IO String -> String 

तो * था हम कर सकते थे अचानक ऐसा आईओ कार्यों कहीं भी बुला, उदाहरण के लिए द्वारा:

index (launchMissiles >> deleteRoot >> return "PWNd!") 

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

* असल में ऐसा फ़ंक्शन है। इसे unsafePerformIO कहा जाता है और इसे के लिए बहुत कहा जाता है, बहुत अच्छे कारण हैं। इसका उपयोग तब तक न करें जब तक आप 100% सुनिश्चित न हों कि आप क्या कर रहे हैं!

+13

मैं कहता हूं कि "इसका उपयोग न करें जब तक आप 200% सुनिश्चित नहीं कर रहे हैं कि आप क्या कर रहे हैं", या यहां तक ​​कि सरल, "नहीं"। –

+6

मैं कहूंगा कि unsafePerformIO के लिए सबसे अच्छा उपयोग कुछ प्रक्रियाओं को खोलना है जो हमेशा एक ही चीज़ को वापस करना चाहिए। यानी एक प्रणाली गणना जो मानक पुस्तकालय द्वारा मूल रूप से समर्थित नहीं है। – alternative

+4

मेरी पुरानी टिप्पणी में जोड़ना जो मुझे अभी एसओ ब्राउज़ करते समय मिला: एफएफआई के लिए भी उपयोगी – alternative

8
fmap index $ readFile "input.txt" 

या

readFile "input.txt" >>= return . index 

आप

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