2012-06-03 16 views
5

से लेज़ी उत्पादन मैं अगले इकाई ट्रांसफार्मर है स्मृति हर समय)।monadic कार्रवाई

मुझे एक ऐसा फ़ंक्शन लागू करने की आवश्यकता है जो पीडीएफ दस्तावेज़ को सहेज लेगा, और मैं इसे आलसी होना चाहता हूं, दस्तावेज़ को निरंतर स्मृति में सहेजना संभव होना चाहिए।

मैं उत्पादन कर सकते हैं आलसी ByteString:

import Data.ByteString.Lazy (ByteString) 
import qualified Data.ByteString.Lazy as BS 
save :: Monad m => Pdf m ByteString 
save = do 
    -- actually it is a loop 
    str1 <- serializeTheFirstObject 
    storeOffsetForTheFirstObject (BS.length str1) 
    str2 <- serializeTheSecondObject 
    storeOffsetForTheSecondObject (BS.length str2) 
    ... 
    strn <- serializeTheNthObject 
    storeOffsetForTheNthObject (BS.length strn) 
    table <- dumpRefTable 
    return mconcat [str1, str2, ..., strn] `mappend` table 

लेकिन वास्तविक उत्पादन पिछले उत्पादन पर निर्भर कर सकते हैं। (विवरण:।। पीडीएफ दस्तावेज़ इसलिए पूर्ण दस्तावेज़ में हर वस्तु के बाइट्स में ऑफसेट के साथ कहा जाता है में शामिल है "संदर्भ तालिका" यह निश्चित रूप ByteString पीडीएफ वस्तु की लंबाई के लिए धारावाहिक है पर निर्भर करता है)

कि save समारोह सुनिश्चित करने के लिए कैसे नहीं होगा कॉलर पर लौटने से पहले पूरे ByteString को मजबूर करें?

क्या कॉलबैक को तर्क के रूप में लेना बेहतर है और जब भी मेरे पास आउटपुट करने के लिए कुछ होता है तो इसे कॉल करना बेहतर होता है?

import Data.ByteString (ByteString) 
save :: Monad m => (ByteString -> Pdf m()) -> Pdf m() 

क्या कोई बेहतर समाधान है?

उत्तर

0

समाधान मैंने पाया अब तक Coroutine उदाहरण:

proc :: Int -> Coroutine (Yield String) IO() 
proc 0 = return() 
proc i = do 
    suspend $ Yield "Hello World\n" (proc $ i - 1) 

main :: IO() 
main = do 
    go (proc 10) 
    where 
    go cr = do 
    r <- resume cr 
    case r of 
     Right() -> return() 
     Left (Yield str cont) -> do 
     putStr str 
     go cont 

यह कॉलबैक के रूप में ही काम करता है, लेकिन फोन करने वाले उत्पादन पीढ़ी पर पूर्ण नियंत्रण है।

0

इसे एक पास में बनाने के लिए आपको (शायद राज्य में) स्टोर करना होगा जहां आपकी अप्रत्यक्ष वस्तुएं लिखी गई हैं। तो बचत को पूर्ण बाइट स्थिति का ट्रैक रखने की आवश्यकता होती है क्योंकि यह काम करता है - मैंने यह नहीं सोचा है कि आपका पीडीएफ मोनड इस कार्य के लिए उपयुक्त है या नहीं। जब आप अंत तक पहुंच जाते हैं तो आप xref सेक्शन बनाने के लिए राज्य में संग्रहीत पते का उपयोग कर सकते हैं।

मुझे नहीं लगता कि दो-पास एल्गोरिदम मदद करेगा।

6 जून को संपादित करें: शायद मैं अब आपकी इच्छा को बेहतर समझता हूं। दस्तावेजों की बहुत तेजी से पीढ़ी के लिए, उदा। एचटीएमएल, नाम में "ब्लेज़" के साथ hackage पर कई पुस्तकालय हैं। तकनीक बाइटस्ट्रिंग पर 'mconcat' का उपयोग करने से बचने और एक मध्यवर्ती 'बिल्डर' प्रकार पर उपयोग करने के लिए है। इसके लिए कोर लाइब्रेरी 'blaze-builder' प्रतीत होती है, जिसका उपयोग 'ब्लेज़-एचटीएमएल' और 'ब्लेज़-टेक्स्टुअल' में किया जाता है।

+0

मैंने समस्या को स्पष्ट करने के लिए अभी 'सेव' फ़ंक्शन के लिए "कार्यान्वयन" जोड़ा है। हां, यह 1-पास एल्गोरिदम होना चाहिए, लेकिन यह कोई मुद्दा नहीं है। मुद्दा स्वयं: जब मैं अंतिम आलसी 'बाइटस्ट्रिंग' का उत्पादन करने के लिए 'मोनकैट' कहता हूं, तो मेरे पास पहले से ही स्मृति है। बहुत बड़ी पीडीएफ फ़ाइल मानते हुए, मेरे पास पर्याप्त स्मृति नहीं है। मैं केवल 'बाइटस्ट्रिंग' नहीं, केवल ऑफसेट स्टोर करना चाहता हूं। ऐसा लगता है कि कॉलबैक दृष्टिकोण समस्या हल करता है, लेकिन मुझे लगता है कि बेहतर समाधान मौजूद होना चाहिए। – Yuras

+0

अजीब, लेकिन मुझे 6 जून को आपके संपादन के बारे में अधिसूचना प्राप्त नहीं हुई थी। कैसे 'ब्लेज़-बिल्डर' मेरी मदद कर सकता है? जब आप 'मैपेंड' करना चाहते हैं तो 'बुलर' निश्चित रूप से तेज है' लेकिन बाइटस्ट्रिंग ', लेकिन समस्या स्मृति उपयोग है, प्रदर्शन नहीं। 'str1',' str2', आदि पहले से ही स्मृति में (बीएस.लेथेंथ द्वारा मजबूर) में होगा 'mconcat' से पहले। – Yuras

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