2011-12-11 13 views
5

मान लीजिए के आधार पर मैं कुछ सामान्य समारोहप्रकार

genericFunc :: a -> b 
genericFunc x = doSomeHardWork 

है एक सामान्य समारोह के लिए एक अलग समारोह शरीर प्रदान करें लेकिन एक विशेष प्रकार के लिए, वहाँ एक बहुत अधिक कारगर तरीका है कि genericFunc किया जा सकता है है।

genericFunc :: ParticularType -> b 
genericFunc x = doSomeEasyWork 

क्या एक ही genericFunc में इन दोनों समारोह निकायों गठबंधन करने के लिए सबसे अच्छा तरीका है इस तरह के है, कि जब ParticularType पर इस्तेमाल किया, यह doSomeEasyWork, लेकिन जब अन्य प्रकार पर इस्तेमाल किया, यह doSomeHardWork जाएगा? मैं विशेष रूप से एक अलग नाम, या विभिन्न मॉड्यूल का उपयोग करने का विकल्प छोड़ रहा हूँ।

मेरा मानना ​​है कि यह एक टाइपक्लास के साथ किया जा सकता है, लेकिन मुझे भाषा प्रमाओं का उपयोग करने वाले समाधानों में अधिक दिलचस्पी है। मेरे पास एक अस्पष्ट इंकलिंग है कि यह भाषा प्रागम्स के साथ किया जा सकता है लेकिन मुझे नहीं पता कि कैसे। यदि आप इन दृष्टिकोणों, और/या किसी अन्य संभावित दृष्टिकोण की तुलना और तुलना करते हैं तो बोनस अंक।

+0

थोड़ा इस सवाल के बारे में सोच से प्रेरित: उदाहरण के लिए, फिर से लिखने संकलक एक समारोह इनलाइन करने का फैसला करता है कि क्या पर निर्भर हो सकता [अगर कुछ एक सूची नहीं है] (http://stackoverflow.com/questions/ 8463777/if-something-is-a-list-in-haskell) –

उत्तर

8

यह कक्षा परिभाषा में सामान्य उद्देश्य विधि को परिभाषित करके और इसे एक उदाहरण में ओवरराइड करके टाइप क्लास के साथ किया जा सकता है। ओवरराइड फ़ंक्शन का हमेशा उपयोग किया जाएगा।

class ContainsInt c where 
    toList :: c -> [Int] 

    -- generic function 
    elem :: Int -> c -> Bool 
    elem n x = Prelude.elem n (toList x) 

instance ContainsInt() where 
    toList _ = [] 

    -- Override the generic function for type() 
    elem _ _ = False 

जीएचसी द्वारा समर्थित एक विकल्प एक पुनर्लेखन नियम का उपयोग करना है। पुनर्लेखन नियम जीएचसी को जब भी संभव हो, एक अभिव्यक्ति को दूसरे स्थानांतरित करने के लिए कहता है। यदि प्रतिस्थापन खराब टाइप किया गया है, तो यह नहीं किया जाएगा, इसलिए आप किसी विशेष संस्करण द्वारा किसी फ़ंक्शन को प्रतिस्थापित करने के लिए इसका उपयोग कर सकते हैं। पुनर्लेखन नियम {-# RULES #-} प्रगामा द्वारा दिया जाता है।

class ContainsInt c where 
    toList :: c -> [Int] 

elem :: ContainsInt c => Int -> c -> Bool 
elem n x = Prelude.elem n (toList x) 

-- Replace 'elem' by 'elemUnit' if it has the same type 
{-# RULES "elem()" forall. elem = elemUnit #-} 

elemUnit :: Int ->() -> Bool 
elemUnit _ _ = False 

पुनर्लेखन नियम संकलक के विवेक पर प्रदर्शन कर रहे हैं, इसलिए किसी भी स्थिति में विशेष समारोह या नहीं कहा जा सकता है।

foo :: ContainsInt c -> Int -> [c] -> [Bool] 
-- Must use the generic function 
foo n cs = map (elem n) cs 

useFoo :: Int -> [()] -> [Bool] 
-- If 'foo' is inlined and 'elem' is not inlined, then this function will contain a rewritable call to 'elem'. 
-- Otherwise rewriting cannot happen. 
useFoo n cs = foo n cs 
2

जीएचसी के साथ, आप RULES pragma का उपयोग कर सकते हैं।

{-# RULES "genericFunc/easy" genericFunc = doSomeEasyWork #-} 

जब भी प्रकार मेल खाते हैं और सामान्य कार्यान्वयन का उपयोग करते हैं तो यह फिर से लिखने के नियम लागू करेगा।

+0

जब भी _GHC साबित कर सकता है कि प्रकार मिलान करते हैं। –

+1

क्या इस "असली कोड में" के कुछ अच्छे उदाहरण हैं जिन्हें मैं देख सकता हूं? –

+1

नियमों का उपयोग न करें, टाइपक्लास का उपयोग करें। यह टाइपक्लास के लिए है। – augustss

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