2012-02-12 11 views
9

फ़ंक्शन संरचना तकनीक और लंबाई के आधार पर हैकेल को एकाधिक पुनर्लेखन नियमों की आवश्यकता क्यों है? इससे बचने का कोई रास्ता है क्या?हास्केल रिवाइट नियम और फ़ंक्शन संरचना

उदाहरण के लिए, निम्नलिखित कोड दिया ...

{-# RULES 
"f/f" forall a. f (f a) = 4*a 
    #-} 
f a = 2 * a 

इस के लिए

test1 = f (f 1) 

काम करता है लेकिन हम

test2 = f . f $ 1 

और

के लिए एक नियम जोड़ने की जरूरत
test3 = f $ f 1 

निम्नलिखित नियम

{-# RULES 
"f/f1" forall a. f (f a) = 4 * a 
"f/f2" forall a. f . f $ a = 4 * a 
"f/f3" forall a. f $ f $ a = 4 * a 
    #-} 

हालांकि के साथ हमें छोड़ रहा है, जब हम स्ट्रिंग इन एक साथ या रचना नियम आग नहीं होने के कुछ अन्य रूपों का उपयोग करें।

test4 = f . f . f $ 1 
test5 = f $ f $ f $ 1 
test6 = f $ 1 

यह क्यों है? क्या मुझे हर संभव कार्यान्वयन के लिए पुनर्लेखन नियम लिखना है?

+1

मुझे वास्तव में पता नहीं है, लेकिन मुझे लगता है कि ऐसा इसलिए है क्योंकि पुनर्लेखन नियम आपके द्वारा आयात किए गए कार्यों पर लागू नहीं होते हैं। और '$' और '.' प्रीलूड से केवल आयातित फ़ंक्शन हैं। –

उत्तर

13

नियम कई मामलों में आग नहीं करता है क्योंकि बहुत सरल समारोह f से पहले नियम आग का मौका मिला inlined है। आप इनलाइनिंग,

{-# INLINE [1] f #-} 

नियम

{-# RULES "f/f" forall a. f (f a) = 4*a #-} 

इन सभी मामलों के लिए सक्रिय किया जाना चाहिए (7.2.2 और 7.4.1 के साथ यहाँ काम किया) में देरी है।

कारण यह है कि नियम matcher अत्यधिक विस्तृत नहीं है, यह नियम के वाक्य रचनात्मक रूप से केवल अभिव्यक्तियों से मेल खाता है (पूरी तरह से सच नहीं है, नियम निकाय कुछ सामान्यीकरण भी गुजरता है)। अभिव्यक्ति f $ f 3 या f . f $ 4 नियम के वाक्य रचनात्मक रूप से मेल नहीं खाते हैं। नियम मिलान करने के लिए, कुछ पुनर्लेखन करना होगा, ($) और (.) को अभिव्यक्ति से मेल खाने से पहले रेखांकित करना होगा। लेकिन अगर आप सरलीकृत के पहले चरण में उल्लिखित होने से f को नहीं रोकते हैं, तो इसे ($) और (.) के समान चलाने में उसके शरीर द्वारा प्रतिस्थापित किया जाता है, इसलिए अगली पुनरावृत्ति में, सरलीकृत को अब f नहीं दिखाई देता है, यह केवल 2*(2*x) देखता है, जो नियम से मेल नहीं खाता है।

3

मैं सोचा होगा कि यह डिफ़ॉल्ट रूप से काम करेगा, लेकिन आप बनाने के लिए दो और फिर से लिखने के नियम जोड़ सकते हैं ./$ lambdas/आवेदन करने के लिए कम है, ताकि यह हमेशा मिलान हो जाएगा:

{-# RULES 
"f/f" forall a. f (f a) = 4*a 

"app" forall f x. f $ x = f x 
"comp" forall f g. f . g = (\x -> f (g x)) 
    #-} 

f a = 3 * a -- make this 3*a so can see the difference 

एक परीक्षण :

main = do 
    print (f . f $ 1) 
    print (f (f 1)) 
    print (f $ f 1) 
    print (f $ f $ 1) 
    print (f $ f $ f $ f $ 1) 
    print (f . f . f . f $ 1) 
    print (f $ f $ f $ 1) 
    print (f . f . f $ 1) 
    print (f $ 1) 

आउटपुट:

4 
4 
4 
4 
16 
16 
12 
12 
3 

यह भी कुछ में काम करेंगे (लेकिन सभी नहीं) अधिक अस्पष्ट सी एएसई, अन्य पुनर्लेखन नियमों के कारण। उदाहरण के लिए, इन सभी का काम करेगा:

mapf x = map f $ map f $ [x] 
mapf' x = map (f.f) $ [x] 
mapf'' x = map (\x -> f (f x)) $ [x] 
संबंधित मुद्दे