2017-07-25 8 views
7

कुछ किताब मैं निम्नलिखित कोड है से`do` और` where` मिश्रण कैसे करें?

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int) 
mutableUpdateIO n = do 
    mvec <- GM.new (n + 1) 
    go n mvec 
    where 
    go 0 v = return v 
    go n v = (MV.write v n 0) >> go (n - 1) v 

mutableUpdateST :: Int -> V.Vector Int 
mutableUpdateST n = 
    runST $ do 
    mvec <- GM.new (n + 1) 
    go n mvec 
    where 
    go 0 v = V.freeze v 
    go n v = (MV.write v n 0) >> go (n - 1) v 

hindent तरह इंडेंट उन्हें टुकड़े। अब मैं सभी ब्रेसिज़ और सेमीकॉलन पेश करना चाहता हूं, इसलिए व्हाइटस्पेस अब और प्रासंगिक नहीं है। सिर्फ इसलिए कि मैं उत्सुक हूँ।

दूसरे उदाहरण से पता चलता है, कि where पूरे runST $ do ... अभिव्यक्ति के अंतर्गत आता है, लेकिन पहले उदाहरण पता चलता है, कि जहां किसी भी तरह go n mvec बयान का एक हिस्सा है। Haskell Report Chapter 2.7 में पढ़ना मैं

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int) 
mutableUpdateIO n = do { 
    mvec <- GM.new (n + 1); 
    go n mvec; 
    where { 
    go 0 v = return v; 
    go n v = (MV.write v n 0) >> go (n - 1) v; 
    } ; } 

की तरह पहले उदाहरण में ब्रेसिज़ और अर्धविराम पेश करने की कोशिश की लेकिन मैं एक पार्स त्रुटि मिलती है। ऐसा क्यों है?

लेआउट hindent क्यों पहला उदाहरण mutableUpdateIO वैध हास्केल का उत्पादन करता है? क्या मेरे ऊपर की कोशिश में ब्रेसिज़ और सेमीकॉलन पेश नहीं किए जाने चाहिए?

+0

'जहां 'af'ik से अलग है। मुझे लगता है कि स्वचालित रूप से कार्यक्षेत्र कहां है। – Carcigenicate

+0

से संबंधित: https://stackoverflow.com/questions/9721354/in-haskell-what-is-the-scope-of-a-where-clause-when-dealing-with-guards – Carcigenicate

+10

'do ...' अभिव्यक्ति है। 'जहां अभिव्यक्तियों को कभी नहीं जोड़ा जाता है, केवल घोषणाओं के लिए। – melpomene

उत्तर

9

where ब्लॉक न तो runST $ do ... अभिव्यक्ति से संबंधित हैं और न ही go n mvec कथन के हैं; वे mutableUpdateIO n = ... घोषणा और mutableUpdateST n = ... घोषणा से संबंधित हैं। ब्रेसिज़ और अर्धविराम इस तरह जाना चाहिए:

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int) 
mutableUpdateIO n = do { 
    mvec <- GM.new (n + 1); 
    go n mvec; 
    } where { 
    go 0 v = return v; 
    go n v = (MV.write v n 0) >> go (n - 1) v; 
    } 

अध्याय 2.7 में रिपोर्ट में अनौपचारिक वर्णन से प्रासंगिक वाक्य यह है:

एक करीबी ब्रेस भी डाला जाता है जब भी वाक्यात्मक युक्त श्रेणी लेआउट सूची समाप्त होती है; यानी, यदि किसी ऐसे बिंदु पर एक अवैध लेक्सम का सामना करना पड़ता है जहां एक करीबी ब्रेस कानूनी होगा, तो एक करीबी ब्रेस डाला जाता है।

where के बाद से एक अभिव्यक्ति के अंदर एक अवैध शब्दिम, इस do ब्लॉक समाप्त हो जाती है और एक करीबी ब्रेस वहाँ डाला जाता है है। यह भी बताता है कि क्यों लेआउट बाधा उत्पन्न कानूनी था।

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