2013-04-25 14 views
5

पर unsafeperformIO का उपयोग करने के जोखिम मैं एक हास्केल एप्लिकेशन बना रहा हूं जो एक अनंत लूप पर यादृच्छिक संख्या उत्पन्न करता है (केवल क्लाइंट द्वारा अनुरोध किए जाने पर)। हालांकि, मुझे केवल उस उद्देश्य के लिए शुद्ध कार्यों का उपयोग करना चाहिए। randomIO को unsafeperformIO के साथ किसी भी कठोर स्थिरता या प्रदर्शन जोखिम के बिना लपेटना सुरक्षित है?randomio

+5

आपको ['random'] (http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:random) या [' randomR'] का उपयोग करना चाहिए (http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:randomR) शुद्ध कोड में। –

+1

नहीं! आप 'unsafeInterleaveIO' को औचित्य देने में सक्षम हो सकते हैं लेकिन यादृच्छिक कुछ भी शुद्ध नहीं है! –

+6

@ फिलिपजेएफ: "यादृच्छिक कुछ भी शुद्ध नहीं है"? मैं कहूंगा कि यादृच्छिक पिवट के साथ चीजें (जगह में नहीं) क्विकॉर्ट पूरी तरह से शुद्ध एल्गोरिदम हैं: यादृच्छिकता प्रदर्शन भिन्नताओं को छोड़कर बाहर से नहीं देखी जा सकती है, जिसका अर्थ केवल 'आईओ' मोनड में कोई अर्थ है। – leftaroundabout

उत्तर

12

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

import System.Random 
import System.IO.Unsafe 
import Data.Int 

slowTrue = unsafePerformIO $ go 
    where 
    go = do 
     x1 <- randomIO 
     x2 <- randomIO 
     if ((x1 :: Int16) == x2) then return True else go 

एक वैश्विक, संभवतः यादृच्छिक चर के निम्नलिखित आकर्षक परिभाषा सुरक्षित नहीं है:

rand :: Bool -> Int 
rand True = unsafePerformIO randomIO 
rand False = 0 

समस्या यह है कि एक ही अभिव्यक्ति अब विभिन्न मूल्यों निकलेगा है:

main = do 
    print (rand True) 
    print (rand True) 

प्रिंट यहां:

-7203223557365007318 
-7726744474749938542 

(कम से कम अनुकूलन के बिना संकलित जब - लेकिन यह unsafePerformIO के अनुचित उपयोग की नाजुकता पर जोर देता है)।

+0

यह एक दिलचस्प सवाल है। शीर्ष स्तर की परिभाषा 'अज्ञात = unsafePerformIO randomIO' वास्तव में सुरक्षित है यदि संकलक केवल एक बार अज्ञात' के शरीर का मूल्यांकन करेगा। लेकिन मुझे पूरा यकीन है कि कंपाइलर के पास इनलाइन और/या कई बार गणना करने का अधिकार है। – ony

+2

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