2011-03-02 12 views
7

मैं निरंतरता मोनाड ट्रांसफार्मर के मोनाडवाइटर के लिए व्युत्पन्न उदाहरण बनाने का प्रयास करता हूं।निरंतर मोनाड ट्रांसफार्मर के लिए मोनाडवाइटर के उदाहरण प्राप्त करना असंभव है?

Occurs check: cannot construct the infinite type: a = (a, w) 
When generalising the type(s) for `listen' 
In the instance declaration for `MonadWriter w (ContT r m)' 
:

instance (MonadWriter w m) => MonadWriter w (ContT r m) where 
    tell= lift . tell 
    listen m= ContT $ \ c -> do 
     (a,w) <- runContT m (listen . c) 
     return (a,w) 

    pass m = undefined 

इसके बाद:

Occurs check: cannot construct the infinite type: r = (r, w1) 
When generalising the type(s) for `listen' 
In the instance declaration for `MonadWriter w (ContT r m)' 

अगला कोशिश यह थी:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-} 

import Control.Monad.Cont 
import Control.Monad.Writer 


instance (MonadWriter w m) => MonadWriter w (ContT r m) where 
    tell= lift . tell 
    listen m= ContT $ \ c -> do 
     (a,w) <- listen $ runContT m (c) 
     return (a,w) 

    pass m = undefined 

यह मैं निम्न त्रुटि देता है: यह कैसे मैं इसे करने की कोशिश की है

क्या कोई भी kn ओउ कैसे सुनो लागू करने और यहां पास करने के लिए? क्या ऐसा कोई कारण है कि एमटीएल में इसके लिए कोई उदाहरण घोषित नहीं किया गया है? कृपया इसे समझने में मेरी मदद करें!

सादर मैरिएन

पुनश्च: मैंने पाया कि Blog Entry at blog.sigfpe.com जहां चर्चा एडवर्ड Kmett की अंत में कहीं कहते हैं:

"(...) मुझे याद है के रूप में, 'पास 'और' स्थानीय 'मौजूदा एमटीएल के साथ समस्याएं उत्पन्न करते हैं जब आप कंटेंट में मिश्रण करना शुरू करते हैं, और शायद अलग वर्गों में फैक्टर होना चाहिए। "

हो सकता है कि होल्डवाइटर से सुनने के लिए भी होल्ड होल्ड हो। तो सबसे आसान समाधान, अगर आप सुन सकते हैं और एक विशेष मामले में पारित करने की जरूरत नहीं है, उन्हें अपरिभाषित छोड़ने के लिए:

instance (MonadWriter w m) => MonadWriter w (ContT r m) where 
    tell= lift . tell 
    listen = undefined 
    pass = undefined 

पुनश्च: (2011-03-11) इस विषय में डाइविंग आगे मैं ले कर आए हैं इस समाधान: (जब के रूप में ContT() पर r टाइप specifiying हम कोशिश कर सकते इस :)

instance (MonadWriter w m) => MonadWriter w (ContT() m) where  
    listen m = do 
     a <- m 
     (_,w) <- lift $ listen $ runContT m (return . (const())) 
     return (a,w) 

यह कम्पाइल हो गया! और चलता है! लेकिन, हां, monadic कार्रवाई दो बार गणना की जानी चाहिए। क्या कोई इसे किसी भी तरह से दो कॉलों को ध्वस्त करने के संकेत के रूप में ले सकता है? फिर हम वांछित कार्यान्वयन प्राप्त करेंगे।

उत्तर

8

मुझे नहीं लगता कि यह संभव है। संदर्भ के लिए, ContT का अर्थ है:

ContT r m a = (a -> m r) -> m r 

यहाँ listen के लिए मेरी प्रारंभिक बिंदु है:

listen m = ContT $ \c -> 
    runCont m (\x -> c (x,w)) 

सवाल है, हम w जहां मिलता है? w गणना से आएगा कि runCont m से पहले करता है, यह हमारे कार्य के साथ हमारे फ़ंक्शन \x -> c (x,w) पर कॉल करता है। यही कारण है कि हम जानकारी पारित करने के लिए crunCont से आता है की जरूरत है, है, इसलिए हम कुछ इस तरह करने की ज़रूरत होगी:

listen m = ContT $ \c -> do 
    rec (r,w) <- listen . runContT m $ \x -> c (x,w) 
    return r 

(LANGUAGE DoRec और MonadFix m जरूरत संदर्भ में)

हालांकि कि typechecks, यह सही नहीं है।w अब संपूर्ण गणना द्वारा लिखित मान है, न कि हमारे निरंतरता \x -> c (x,w) पर कॉल करने से पहले केवल भाग।

क्या आप देखते हैं कि आपको क्या करना होगा? मुझे पता है कि मेरा जवाब अनिवार्य रूप से है "मुझे लगता है कि यह असंभव है क्योंकि मैं इसे करने का कोई तरीका नहीं सोच सकता" (कोनाल इलियट ने "कल्पना की कमी के कारण सबूत" कहा है), लेकिन मुझे लगता है कि इस समय मेरी कल्पना की कमी सही है। इससे पहले कि हमें उस पर ध्यान देने का मौका मिले, हमें जो जानकारी चाहिए उसे नष्ट कर दिया गया है।

मेरा मानना ​​है कि इस उदाहरण Codensity इकाई ट्रांसफार्मर के साथ संभव है:

newtype CodensityT m a = CodensityT { runCodensityT :: forall r. (a -> m r) -> m r } 

जो आप ऐसे मामलों में जहां यह करता है में Cont रूप में एक ही प्रदर्शन में सुधार देता है, लेकिन callCC समर्थन नहीं करता। ऐसा इसलिए है क्योंकि आप r जो भी चाहते हैं उसके साथ गणना के बीच में runCodensityT कर सकते हैं।

listen m = CodensityT $ \c -> listen (runCodensityT m return) >>= c 

शायद callCC समस्या है। अगर आप listen और callCC संयोजन वाले उदाहरण के साथ आ सकते हैं तो मैं आश्चर्यचकित नहीं होगा जो एक विरोधाभास पैदा करेगा।

+0

luqui! आपके उत्तर के लिए धन्यवाद। वैसे, आप मुझे MonadFix समझने के लिए लाया! – makelc

+0

मैंने अभी प्रश्न संपादित किया है और ब्लॉग से कुछ जानकारी जोड़ दी है जहां मुझे संकेत मिले हैं कि एमटीएल में कुछ विधियां कंटेट के साथ मिश्रित होने पर समस्याएं पैदा करती हैं। विनम्र, मैरियन – makelc

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