2012-03-17 11 views
10

मैं एक दोस्त को हास्केल सीखने में मदद कर रहा हूं और उसने हाल ही में इस तरह का कोड बनाया है, जो रनटाइम पर एक सीपीयू-बर्निंग लूप जांचता है और बनाता है। मैं इस से पूरी तरह से परेशान हूँ।नियंत्रण आयात क्यों करता है। अनुप्रयोग इस खराब कोड को चेक टाइप करने की अनुमति देता है?

import Control.Monad 
import Control.Applicative 

main = forever putStrLn "Hello, infinity" 

जो चेक टाइप नहीं करना चाहिए, लेकिन करता है। सही संस्करण स्पष्ट रूप से होगा:

main = forever $ putStrLn "Hello, infinity" 

क्या अजीब और मेरे लिए आश्चर्य की बात है कि आप के साथ और Control.Applicative आयात किए बिना अलग परिणाम प्राप्त है। आयात करने के बिना, यह जाँच टाइप नहीं करता है:

Prelude Control.Monad> forever putStrLn "Hello, infinity" 

<interactive>:1:1: 
    No instance for (Monad ((->) String)) 
     arising from a use of `forever' 
    Possible fix: add an instance declaration for (Monad ((->) String)) 
    In the expression: forever putStrLn "Hello, infinity" 
    In an equation for `it': it = forever putStrLn "Hello, infinity" 

मैं Control.Applicative के लिए स्रोत में ((->) String के लिए एक इकाई उदाहरण नहीं दिख रहा है, तो मैं के अपने प्रयोग के कारण कुछ अजीब हो रहा है अनुमान लगा रहा हूँ नियंत्रण। श्रेणी या नियंत्रण। तीर, लेकिन मुझे नहीं पता। तो मुझे लगता है कि मेरे पास दो प्रश्न हैं:

  1. नियंत्रण आयात करने के बारे में क्या है। आवेदन यह है कि ऐसा होने देता है?
  2. जब यह अनंत लूप में प्रवेश करता है तो क्या हो रहा है? हास्केल वास्तव में उस मामले में निष्पादित करने का प्रयास कर रहा है?

धन्यवाद,

उत्तर

13

वहाँ (->) String के लिए एक उदाहरण नहीं है, लेकिन वहाँ (->) e के लिए एक उदाहरण है ... और कहा कि उदाहरण के बहुत, बहुत कई स्थितियों में उपयोगी है।

instance Monad ((->) e) where 
    return x = \e -> x 
    m >>= f = \e -> f (m e) e 

forever m = m >> forever m = m >>= \_ -> forever m 

अब, forever putStrLn क्या करना है: दूसरे प्रश्न के लिए, हम कार्यों के लिए forever पर एक नज़र और वर्ग उदाहरण ले लेना चाहिए?

forever putStrLn 
    = putStrLn >>= \_ -> forever putStrLn 
    = \e -> (\_ -> forever putStrLn) (putStrLn e) e 
    = \e -> (forever putStrLn) e 
    = forever putStrLn 

... यह सिर्फ एक शुद्ध अनंत लूप, मूल रूप से loop = loop के समान है।

प्राप्त करने के लिए (के रूप में यह जाना जाता है) क्या पाठक इकाई के साथ हो रहा है के लिए कुछ अंतर्ज्ञान, सभी monads section on Reader के बारे में, the documentation पर एक नज़र डालें, और कुछ Typeclassopedia जो मदद कर सकता है भर में छिड़का संकेत दिए हैं।

+0

क्या आप विस्तार कर सकते हैं कि '(->) ई' के लिए क्या उदाहरण उपयोगी है? –

+4

@DanielLyons यह उपयोगी है जब आपके पास कई फ़ंक्शन हैं जिन्हें सभी को कुछ साझा कॉन्फ़िगरेशन जानकारी तक पहुंच की आवश्यकता है। फिर आप लिख सकते हैं (उदाहरण के लिए) 'foo >> = bar >> = baz' हर जगह पर्यावरण को दोहराने के बजाय '\ e -> x = foo e; वाई = बार एक्स ई; z = baz y e y y में। –

6

Control.Applicative आयात Control.Monad.Instances आयात करता है, और इसलिए Control.Monad.Instances से उदाहरणों को फिर से निर्यात करता है। इसमें Functor और Monad((->) r) के उदाहरण शामिल हैं।