के बारे में jbapple के शानदार जवाब पर रिफ़िंग replicate
, लेकिन इसके बजाय replicateA
(जो replicate
पर बनाया गया है) का उपयोग करके , मैं निम्नलिखित के साथ आया:
--Unlike fromList, one needs the length explicitly.
myFromList :: Int -> [b] -> Seq b
myFromList l xs = flip evalState xs $ Seq.replicateA l go
where go = do
(y:ys) <- get
put ys
return y
myFromList
(थोड़े अधिक कुशल संस्करण में) पहले से परिभाषित है और आंतरिक रूप से Data.Sequence
उंगली के पेड़ों के निर्माण के लिए उपयोग किया जाता है जो कि प्रकार के परिणाम हैं।
सामान्य तौर पर, अंतर्ज्ञान replicateA
सरल है। एप्लिकेशनट्रीट्री फ़ंक्शन के replicateA
शीर्ष पर बनाया गया है। एक आकार के पेड़ का एक टुकड़ा लेता है , और इस की प्रतियां युक्त एक अच्छी तरह से संतुलित पेड़ का उत्पादन करता है । के लिए मामलों 8 अप करने के लिए (एक उंगली) हार्ड कोडित रहे हैं। इसके ऊपर कुछ भी, और यह खुद को पुनरावर्ती रूप से आमंत्रित करता है। "आवेदक" तत्व बस यह है कि यह पेड़ के निर्माण को उन प्रभावों से फैलाता है, जैसे कि उपरोक्त कोड, स्थिति।applicativeTree
m
n
n
Deep
go
समारोह है, जो दोहराया जाता है, बस एक कार्रवाई है, जो वर्तमान स्थिति हो जाता है ऊपर से एक तत्व दिखाई दे, और शेष को बदल देता है। प्रत्येक आह्वान पर, यह इस प्रकार इनपुट के रूप में दी गई सूची को और नीचे ले जाता है।
कुछ और ठोस नोट
main = print (length (show (Seq.fromList [1..10000000::Int])))
कुछ सरल परीक्षणों पर, इसने एक दिलचस्प प्रदर्शन ट्रेडऑफ़ प्राप्त किया। ऊपर मुख्य समारोह लगभग 1/3 से कम चला गया myFromList के साथ की तुलना में fromList
। दूसरी ओर, myFromList
2MB के एक निरंतर ढेर का fromList
उपयोग किया , जबकि मानक 926MB तक का उपयोग किया। वह 926MB एक बार में पूरी सूची को मेमोरी में रखने की आवश्यकता से उत्पन्न होती है। इस बीच, समाधान myFromList
एक आलसी स्ट्रीमिंग फैशन में संरचना का उपभोग करने में सक्षम है। इस तथ्य से गति के परिणाम के myFromList
रूप में कई आवंटन (राज्य निर्माण के विनाश के रूप में जोड़ी निर्माण / विनाश के परिणामस्वरूप) के रूप में लगभग दो बार प्रदर्शन करना चाहिएfromList
। हम उन आवंटन को एक सीपीएस-रूपांतरित राज्य मोनड में स्थानांतरित करके समाप्त कर सकते हैं, लेकिन इसके परिणामस्वरूप किसी भी समय अधिक स्मृति को धारण किया जा सकता है, क्योंकि आलस्य के नुकसान को गैर-स्ट्रीमिंग तरीके से सूची का पता लगाने की आवश्यकता होती है।
दूसरी ओर, अगर एक शो के साथ पूरे अनुक्रम को मजबूर करने के बजाय, मैं सिर्फ सिर या आखिरी तत्व को निकालने के लिए आगे बढ़ता हूं, तो myFromList
तुरंत एक बड़ी जीत प्रस्तुत करता है - सिर के तत्व को निकालना लगभग तुरंत है, और अंतिम तत्व को निकालना 0.8 है । इस बीच, मानक के साथ fromList
, सिर या अंतिम तत्व को निकालने में ~ 2.3 सेकंड का खर्च आता है।
यह सब विवरण है, और पवित्रता और आलस्य का परिणाम है। म्यूटेशन और रैंडम एक्सेस वाली स्थिति में, मुझे लगता है कि replicate
समाधान सख्ती से बेहतर होगा।
हालांकि, यह सवाल उठाता है कि क्या इस तरह के फिर से लिखने का एक तरीका है applicativeTree
जो myFromList
सख्ती से अधिक कुशल है। मुद्दा यह है, मुझे लगता है, कि पेड़ से स्वाभाविक रूप से अलग-अलग क्रम में लागू किया जाता है, लेकिन मैंने पूरी तरह से काम नहीं किया है कि यह कैसे काम करता है, या अगर इसे हल करने का कोई तरीका है।