2010-04-28 16 views
6

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

{-# OPTIONS_GHC -XFlexibleInstances #-} 

instance Show (t -> t-> t) where 
show (+) = "plus" 
show (-) = "minus" 

main = print [(+),(-)] 

रिटर्न

[plus,plus] 

मैं सिर्फ पहली जगह में एक नश्वर पाप मुद्रण कार्यों को करने कर रहा हूँ या वहाँ किसी तरह मैं इसे ठीक से पूरे करने से मिल सकती है?

संपादित करें: मुझे लगता है मैं निम्न चेतावनी हो रही है:

Warning: Pattern match(es) are overlapped 
     In the definition of `show': show - = ... 

मैं अभी भी नहीं जानता कि क्यों यह ओवरलैप करता है, या यह कैसे को रोकने के लिए।

उत्तर

9

के रूप में केवल कंस्ट्रक्टर्स पर और sepp2k MtnViewMark कहा, तुम पहचानकर्ता के मूल्य पर पैटर्न मैच नहीं कर सकते हैं, और कुछ मामलों, निहित समानता की जाँच में। इसलिए, आपका उदाहरण (+) की बाहरी परिभाषा को छायांकित करने वाली प्रक्रिया में, पहचानकर्ता को किसी भी तर्क को बाध्य कर रहा है। दुर्भाग्यवश, इसका मतलब है कि आप जो करने की कोशिश कर रहे हैं वह कभी भी काम नहीं करेगा और कभी नहीं कर सकता।

जो आप पूरा करना चाहते हैं उसके लिए एक सामान्य समाधान एक उचित अंक show उदाहरण के साथ "अंकगणितीय अभिव्यक्ति" बीजगणितीय डेटा प्रकार को परिभाषित करना है। ध्यान दें कि आप अपनी अभिव्यक्ति प्रकार को Num का एक उदाहरण बना सकते हैं, जिसमें "लिटल" कन्स्ट्रक्टर में लिपटे संख्यात्मक अक्षर और (+) जैसे ऑपरेशन ऑपरेशन के लिए एक कन्स्ट्रक्टर के साथ संयुक्त तर्कों को वापस कर सकते हैं। यहां एक त्वरित, अपूर्ण उदाहरण है:

data Expression a = Literal a 
        | Sum (Expression a) (Expression a) 
        | Product (Expression a) (Expression a) 
        deriving (Eq, Ord, Show) 

instance (Num a) => Num (Expression a) where 
    x + y = Sum x y 
    x * y = Product x y 
    fromInteger x = Literal (fromInteger x) 

evaluate (Literal x) = x 
evaluate (Sum x y) = evaluate x + evaluate y 
evaluate (Product x y) = evaluate x * evaluate y 

integer :: Integer 
integer = (1 + 2) * 3 + 4 

expr :: Expression Integer 
expr = (1 + 2) * 3 + 4 

GHCi में इसे बाहर की कोशिश कर रहा:

> integer 
13 
> evaluate expr 
13 
> expr 
Sum (Product (Sum (Literal 1) (Literal 2)) (Literal 3)) (Literal 4) 
+0

यह शानदार है, धन्यवाद। (और नीचे दिए गए समाधान से कहीं अधिक सुरुचिपूर्ण।) –

+0

@ सेन डी: यह भी एक अच्छा उदाहरण बनाता है कि आपका मेगा हैक असफल होगा - विचार करें कि क्या होगा यदि इसका उपयोग 'अभिव्यक्ति इंटीगर' मानों पर ऑपरेटर के साथ किया गया था । 'कोड '2 के बराबर उचित उदाहरण होने के बावजूद' 6 6' 'लिटरल 8' के बराबर नहीं है। –

6

यह ओवरलैप करता है क्योंकि यह (+) का उपयोग एक चर के रूप में करता है, जिसका अर्थ है आरएचएस पर पहचानकर्ता + उस समारोह से बंधेगा जिसे आपने शो कहा था।

आपके इच्छित तरीकों पर पैटर्न मिलान का कोई तरीका नहीं है।

9

यहां इस बारे में सोचने का एक तरीका है। विचार करें:

answer = 42 
magic = 3 

specialName :: Int -> String 
specialName answer = "the answer to the ultimate question" 
specialName magic = "the magic number" 
specialName x = "just plain ol' " ++ show x 

क्या आप देख सकते हैं कि यह क्यों काम नहीं करेगा? पैटर्न मिलान में answer बाहरी चर पर answer से भिन्न एक चर है। बजाय, आप इस तरह लिखने के लिए होगा:

answer = 42 
magic = 3 

specialName :: Int -> String 
specialName x | x == answer = "the answer to the ultimate question" 
specialName x | x == magic = "the magic number" 
specialName x = "just plain ol' " ++ show x 

वास्तव में, यह सिर्फ तुम क्या जब आप एक पैटर्न में स्थिरांक लिखने पर जा रहा है है। यही कारण है:

digitName :: Bool -> String 
digitName x | x == 0 = "zero" 
digitName x | x == 1 = "one" 
digitName _ = "math is hard" 

आप समारोह (+) करने के लिए बाध्य के खिलाफ मैच के लिए सिर्फ प्रतीक (+), आप 'के लिए कुछ भी बाँध के बजाय चाहते हैं के बाद से:

digitName :: Bool -> String 
digitName 0 = "zero" 
digitName 1 = "one" 
digitName _ = "math is hard" 

के बराबर कुछ करने के लिए संकलक द्वारा परिवर्तित हो जाता है अपने कोड लिखने की ज़रूरत d के रूप में:

instance Show (t -> t-> t) where 
show f | f == (+) = "plus" 
show f | f == (-) = "minus" 

लेकिन, इस की आवश्यकता होगी कि कार्यों eq के लिए तुलनीय थे uality। और यह सामान्य रूप से एक अपरिहार्य समस्या है।

आप यह सोच सकते हैं कि आप फंक्शन पॉइंटर्स की तुलना करने के लिए रन-टाइम सिस्टम से पूछ रहे हैं, लेकिन भाषा स्तर पर, हास्केल प्रोग्रामर को पॉइंटर्स तक पहुंच नहीं है। दूसरे शब्दों में, आप Haskell (*) में मानों के संदर्भों में हेरफेर नहीं कर सकते हैं, केवल खुद को मानते हैं। यह हास्केल की शुद्धता है, और लाभ पारदर्शी पारदर्शिता है।

(*) MVar एस और IO मोनैड में ऐसी अन्य वस्तुओं एक और मामला है, लेकिन उनका अस्तित्व बिंदु को अमान्य नहीं करता है।

+0

यह सब स्पष्ट हो जाता है! मैंने ईक के उदाहरण (+) और (-) बनाने की कोशिश की लेकिन जाहिर है (अब) या तो समझ में नहीं आता है। महान उत्तर के लिए धन्यवाद। –

1

इसे अपने आप को एक मेगा हैक साथ हल।

instance (Num t) => Show (t -> t-> t) where 
show op = 
    case (op 6 2) of 
     8 -> "plus" 
     4 -> "minus" 
     12 -> "times" 
     3 -> "divided" 
संबंधित मुद्दे