2013-02-01 16 views
13

हास्केल में दो अलग-अलग लेखक-प्रकार के मोनैड क्यों हैं? मेरे लिए सहजता से, "सख्त लेखक मोनैड" पढ़ने का अर्थ है कि <> सख्त है, ताकि लॉग में कोई थंक बिल्डअप न हो। हालांकि, स्रोत कोड देख, यह पता चला है कि ऐसा नहीं है:लेखक का आलसी/सख्त संस्करण होने का क्या मतलब है?

-- Lazy Writer 
instance (Monoid w, Monad m) => Monad (WriterT w m) where 
-- ... 
m >>= k = WriterT $ do 
    ~(a, w) <- runWriterT m 
    ~(b, w') <- runWriterT (k a) 
    return (b, w <> w') 

सख्त संस्करण पैटर्न अकाट्य नहीं हैं, अर्थात ~ याद कर रहे हैं। तो ऊपर क्या होता है कि m और k a का मूल्यांकन नहीं किया जाता है, लेकिन थंक्स के रूप में संग्रहीत किया जाता है। सख्त संस्करण में, उनका मूल्यांकन यह जांचने के लिए किया जाता है कि वे ट्यूपल पैटर्न से मेल खाते हैं या नहीं, परिणाम <> पर खिलाया जाता है। दोनों मामलों में, >>= का मूल्यांकन तब तक नहीं किया जाता जब तक कि कुछ वास्तव में परिणामी मूल्य की मांग नहीं करता। तो जिस तरह से मैं समझता हूं कि आलसी और सख्त संस्करण दोनों एक ही काम करते हैं, सिवाय इसके कि >>= की परिभाषा के अंदर उनके पास एक अलग जगह में थंक है: आलसी runWriterT थंक्स का उत्पादन करती है, सख्त <> थंक्स उत्पन्न करती है।

यह मैं दो सवालों के साथ छोड़ देता है:

  1. ऊपर सही है, या मैं यहाँ मूल्यांकन गलत करते हैं?
  2. क्या मैं अपना खुद का रैपर और उदाहरण लिखने के बिना सख्त <> पूरा कर सकता हूं?
+3

प्रश्न 1 के लिए, उत्तर http://stackoverflow.com/questions/13186512/difference-between-haskells-lazy-and-strict-monads-or-transformers –

उत्तर

15

आप पहली बार अवलोकन सही है, लेकिन इस भेद के बीच यह भेद महत्वपूर्ण है।

Lazy और Strict लॉग प्रकार में सख्तता के बारे में नहीं हैं, बल्कि इसके बजाय जोड़ी में कठोरता के बारे में हैं।

ये उठते हैं क्योंकि हास्केल में एक जोड़ी को अद्यतन करने के दो संभावित तरीके हैं।

bimap f g (a,b) = (f a, g b) 

या

bimap f g ~(a,b) = (f a, g b) 

उत्तरार्द्ध के रूप में

bimap f g p = (f (fst p), g (snd p)) 

इन दोनों के बीच अंतर जब आप पहली बार मामले में bimap को आर्ग गुजरती हैं, जोड़ी है वह यह है कि एक ही है तुरंत मजबूर

बाद के मामले में जोड़ी को तत्काल मजबूर नहीं किया जाता है, लेकिन इसके बजाय मैं आपको (,) दो गैर-सख्त गणनाओं से भरा हुआ हूं।

इसका मतलब है कि

fmap f _|_ = _|_ 

पहले मामले में लेकिन

fmap f _|_ = (_|_, _|_) 
दूसरा lazier जोड़ी मामले में

!

दोनों एक जोड़ी की अवधारणा की विभिन्न व्याख्याओं के तहत सही हैं। एक जोड़ी को नाटक करके आप पर मजबूर किया जाता है, यह स्पष्ट रूप से एक जोड़ी है, जिसमें उसके पास कोई भी दिलचस्प _|_ नहीं है। दूसरी तरफ, डोमेन की व्याख्या गैर-सख्त के रूप में होती है।जितना संभव हो सके उतने प्रोग्राम हो सकते हैं जितना संभव हो सके Lazy संस्करण में।

(,) e एक पूरी तरह से स्वीकार्य Writer है, इसलिए यह समस्या को दर्शाता है।

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

नोट, किसी भी मामले में यह 'लॉग' तर्क में सख्त नहीं है। एक बार जब आप सख्तता लेते हैं तो आप उचित साझेदारी खो देते हैं और Monad होने के लिए तकनीकी रूप से बंद कर देते हैं। =/

क्योंकि यह एक मोनड नहीं है, हम इसे mtl में आपूर्ति नहीं करते हैं!

कि के साथ, हम अपने दूसरे प्रश्न का समाधान कर सकते हैं:

वहाँ कुछ समाधान हालांकि रहे हैं। आप State के शीर्ष पर नकली Writer बना सकते हैं। असल में आपको नाटक करते हुए आपको राज्य का तर्क नहीं दिया जाता है। और बस राज्य में शामिल हों क्योंकि आप tell करेंगे। अब आप इसे सख्ती से कर सकते हैं, क्योंकि यह हर बाध्य के हिस्से के रूप में आपकी पीठ के पीछे नहीं हो रहा है। State सिर्फ कार्रवाई के बीच असंबद्ध राज्य से गुज़र रहा है।

shout :: Monoid s => s -> Strict.StateT s m() 
shout s' = do 
    s <- get 
    put $! s <> s' 

लेकिन यह मतलब है कि आप उत्पादन के लिए अपने संपूर्ण State इकाई के लिए मजबूर, और lazily Monoid के कुछ हिस्सों का उत्पादन नहीं कर सकते हैं, लेकिन आप कुछ है कि प्रचालन क्या एक सख्त प्रोग्रामर उम्मीद करेंगे के करीब है मिलता है। दिलचस्प बात यह है कि यह केवल Semigroup के साथ भी काम करता है, क्योंकि mempty का उपयोग केवल प्रभावी है जब आप runState प्रारंभ करते हैं।

+1

आलसी जोड़े के बारे में निरीक्षण: सामान्य '(,) 'अतिरिक्त नीचे की वजह से स्पष्ट अर्थ में एक उत्पाद नहीं है। यदि हास्केल में 'seq' नहीं था, तो बस एक प्रकार के डेटा के साथ एक मॉड्यूल को परिभाषित कर सकता है, एक बी = जो एक बी को जोड़ता है जो कि कन्स्ट्रक्टर का पर्दाफाश नहीं करता था, लेकिन इन जोड़ों को बनाने और पहले और दूसरे मान प्राप्त करने के लिए कार्यों का पर्दाफाश करता था। मॉड्यूलरिटी इसे वास्तविक उत्पाद के रूप में अवलोकन कर सकती है (आईएमओ जो काफी अच्छी है)। या चर्च एन्कोडिंग का उपयोग करें। हालांकि हमारे पास 'seq' है, और सख्त भाषाओं में उत्पाद नहीं हो सकते हैं, इसलिए जब हम गणितीय सटीकता की बात करते हैं तो हम भाग्य से बाहर हैं। –

+0

क्या आप उदाहरण दे सकते हैं कि सख्त संस्करण उपयोगी हो सकता है? मैं समझ नहीं पा रहा हूं कि यह आलसी के लिए कभी भी बेहतर कैसे हो सकता है। –

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