2014-07-24 5 views
6

में गणनाओं को समयबद्ध करना मैं Control.Monad.Random लाइब्रेरी का उपयोग कर टाइमआउट के साथ हास्केल में यादृच्छिक गणना का मूल्यांकन करना चाहता हूं। निम्नलिखित काम करता है ठीक:हास्केल - रैंड मोनड

ghci> import System.Timeout 
ghci> import Control.Monad.Random 
ghci> timeout 1000 . evalRandIO $ getRandomR (True, False) 
Just True 

हालांकि, इस पद्धति अगर हम (नीचे करने के लिए अर्थात मूल्यांकन करता है) प्रकार Rand StdGen a कि कभी नहीं समाप्त हो जाता है की एक गणना है काम करने के लिए प्रतीत नहीं होता। उदाहरण के लिए:

ghci> let f = f :: Rand StdGen Bool 
ghci> timeout 1000 $ evalRandIO f 
Just 

यहाँ GHCi प्रिंट "बस" और फिर अनिश्चित काल के लिए f मूल्यांकन करने के लिए कोशिश कर रहा है लटका हुआ है। क्या कोई ऐसा व्यक्ति कर सकता है जो हास्केल रनटाइम के बारे में अधिक जानता है, मैं यह समझाता हूं कि ऐसा क्यों होता है, और इसके आसपास कैसे जाना है? मेरा अनुमान है कि अभिव्यक्ति evalRandIO f का मूल्यांकन डब्ल्यूएचएनएफ के लिए किया जाता है और इसलिए timeout 10 सोचता है कि गणना समाप्त होने जा रही है, लेकिन मुझे वास्तव में कोई जानकारी नहीं है।

उत्तर

5

यह और अधिक समझ बनाने सकता है यदि आप की तरह

> Just x <- timeout 1000 $ evalRandIO f 
> :t x 
x :: Bool 
> x 
Interrupted. 

गणना में ही पूरा कर रहा है, अर्थात् यह WHNF तक पहुंच गया है कुछ करने के लिए थे, इसलिए timeout इसे पकड़ नहीं करता है। timeout 1000 फ़ंक्शन स्वयं पूर्ण हो जाता है और Just undefined देता है। एक उदाहरण है जहाँ आप एक नीचे मूल्यांकन को पकड़ने के लिए timeout प्राप्त कर सकते हैं होगा

> import Control.DeepSeq 
> :set +m -- Multiline mode 
> let f :: Bool 
|  f = f 
| 
> timeout 1000000 $ deepseq f (return f) 
Nothing 

आप देखेंगे कि यह एक पल के लिए लटका हुआ है, तो रिटर्न Nothing जब deepseqf का मूल्यांकन समाप्त नहीं होती तो यह return f प्रदर्शन कर सकते हैं।

तो हाँ, आपकी समस्या इस तथ्य से उत्पन्न हो रही है कि f = f एनएफ के बजाय डब्ल्यूएचएनएफ का मूल्यांकन किया जाता है। एनएफ को मजबूर करने के लिए, आपको deepseq जैसे कुछ उपयोग करने की आवश्यकता है। एक और संभवतः सरल उदाहरण केवल $! ऑपरेटर का उपयोग करना होगा, जैसे:

> let f :: Rand StdGen Bool 
|  f = f 
| 
> timeout 1000000 $ evalRandIO $! f 
Nothing 
+0

धन्यवाद! मुझे स्पष्ट रूप से seq/deepseq और हास्केल रनटाइम के बारे में जानने के लिए बहुत कुछ है। – user3873438

+0

@ user3873438 निष्पक्ष होने के लिए, मुझे इसे स्वयं समझने के लिए एक जीएचसीआई सत्र लोड करना पड़ा। आलस्य कुछ रोचक समस्याओं का कारण बनती है, लेकिन अधिकांश समय आपको इसके बारे में भी सोचना नहीं पड़ता है। यह ज्यादातर तब होता है जब आपको ऐसी समस्याएं होती हैं जिनके लिए किसी विशेष क्रम में चीजों की आवश्यकता होती है, जिन्हें आपको सख्तता के बारे में चिंता करने की आवश्यकता होती है, और इस मामले में आप 'टाइमआउट 1000' के अंत से पहले' evalRandIO f' होना चाहते थे। इस तरह के रिश्ते के साथ, सख्तता के साथ स्पष्ट होना महत्वपूर्ण है, जो 'deepseq' और '$!' है। – bheklilr

+0

आपको अंतरिक्ष लीक और समांतरता के लिए आलस्य के बारे में चिंता करने की भी आवश्यकता है। – PyRulez

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