2014-10-19 18 views
6

फोल्डिंग समाप्त गैर हमें एक अन्यथा को तोड़ते पर विचार करें:अनुवाद योजना कॉल/सीसी हास्केल callCC को

(call/cc (lambda (folded) 
    (stream-fold 
    (lambda (acc v) 
     (if (< v 5) 
     (cons v acc) 
     (folded acc))) 
    '() 
    (in-naturals 0)))) 
; returns '(4 3 2 1 0) 

ऊपर कोड की हास्केल बराबर होगा

callCC $ \folded -> foldl (\acc v -> if v < 5 then v:acc else folded acc) [] [0..] 

इस कोड को करता है अभिव्यक्त संकलन में एक अनंत प्रकार का निर्माण करने में असमर्थ होने के बारे में संकलित और शिकायत नहीं करते हैं। मुझे पहले से ही एक विचार है कि वाई संयोजक जैसे मामलों में इस तरह की त्रुटि को कैसे खत्म किया जाए, लेकिन वही दृष्टिकोण यहां काम नहीं कर रहा है। इस तरह की स्थिति के लिए सही दृष्टिकोण क्या है?

+6

'foldl' के बजाय' foldM' का उपयोग करें। यहां आपके पास यह है कि 'v: acc' और' folded acc 'एक ही प्रकार को वापस नहीं करते हैं। –

उत्तर

6

हाँ; जे के रूप में अब्राहमसन कहते हैं,

import Control.Monad.Trans.Cont 
import Control.Monad 

bar :: Cont r [Int] 
bar = callCC $ \folded -> 
    foldM (\acc v -> do 
     when (v >= 5) $ folded acc 
     return $ v : acc) [] [0..] 

thing = runCont bar id 

काम करता है।

+1

उत्तर के लिए धन्यवाद। यह इस मामले में काम करता है, लेकिन यह विशेष रूप से विशेष प्रतीत होता है। क्या कॉल कोड/सीसी के साथ हास्केल में स्कीम कोड का अनुवाद करने के लिए कोई सामान्य दृष्टिकोण है या क्या मुझे हमेशा हस्ताक्षरों को देखकर प्रत्येक मामले को व्यक्तिगत रूप से मानना ​​चाहिए? – zabolekar

1

सबसे पहले, योजना कॉल/सीसी और हास्केल callCC, कुछ हद तक अलग बातें हैं के रूप में पृष्ठ पर समझाया undelimited continuations are not functions

मुख्य मुद्दा यह है कि आप कॉल/सीसी बिल्कुल जरूरत नहीं हो सकता है - भले में योजना। लूप से तोड़ने का आपका उदाहरण अपवादों का उपयोग करके बेहतर ढंग से लागू किया गया है - दक्षता के दृष्टिकोण से बेहतर (निरंतरता को कैप्चर करने की आवश्यकता नहीं है जिसे आप किसी भी तरह से उपयोग नहीं करेंगे), और बेहतर अवधारणात्मक रूप से। यदि कार्य वर्तमान निरंतरता को निरस्त करना है, तो उस उद्देश्य के लिए बिल्कुल औजार हैं। आर 7 आरएस ने इसे पहचाना है और अपवाद पेश किए हैं। हास्केल में अपवादों का उपयोग करने के लिए, त्रुटि या या तो मोनड का उपयोग करें। उदाहरण के लिए, अपने कोड

baz :: Either [Int] [Int] 
baz = foldM (\acc v -> do 
     when (v >= 5) $ Left acc 
     return $ v : acc) [] [0..] 

thing1 = either id id baz 

में ऑपरेटर कॉल/सीसी योजना के लिए शुरू की है जब वहाँ नियंत्रण ऑपरेटरों के साथ छोटा सा अनुभव था। अब हमारे पास बहुत अनुभव है, और कॉल/सीसी की कई गंभीर कमीएं प्रकाश में आई हैं। यदि आप अधिक जानकारी में रुचि रखते हैं, तो निम्न पृष्ठ कॉल/सीसी के साथ समस्याओं के बारे में महान विवरण में बात करता है। An argument against call/cc

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