2012-09-05 10 views
8

मैं है निम्नलिखित हास्केल कोड:उम्मीद मिलान नहीं हो पाया प्रकार `इंट 'वास्तविक प्रकार के साथ` पूर्णांक'

-- Problem 69 

import ProjectEuler 

phi :: Integer -> Integer 
phi n = n * product [p - 1 | p <- primeDivisors n] `div` product [p | p <- primeDivisors n] 
-- primeDivisors n is a list of the prime divisors of n 

maxRatio :: (Int, Int, Double) -> (Int, Int, Double) -> (Int, Int, Double) 
maxRatio [email protected](_, _, x) [email protected](_, _, y) 
    | x > y = t1 
    | otherwise = t2 

main = print (foldl 
       maxRatio 
       (0, 0, 0.0) 
       [(n, phi n, ratio) | n <- [2..max], let ratio = fromIntegral n/(fromIntegral (phi n))] 
      ) 
    where max = 1000 

जो निम्न त्रुटि देता है:

Couldn't match expected type `Int' with actual type `Integer' 
In the expression: n 
In the expression: (n, phi n, ratio) 
In the third argument of `foldl', namely 
    `[(n, phi n, ratio) | 
     n <- [2 .. max], 
     let ratio = fromIntegral n/(fromIntegral (phi n))]' 

मैं में संदेह है कि ट्रिपल (0, 0, 0.0) 0 के Int हैं। 0 हमेशा Int टाइप करें या इस मामले में ghci Int के रूप में इस प्रकार को कम कर रहा है? यदि बाद में, मैं इसे Integer टाइप करने के लिए कैसे मजबूर करूं? या क्या कोई और चीज है जो इस त्रुटि का कारण बनती है?

उत्तर

15

का उपयोग हास्केल आम तौर पर इस तरह के 0 जो कुछ भी उचित प्रकार आप उन्हें जरूरत होने के लिए के रूप में के रूप में संख्यात्मक शाब्दिक के प्रकार के अनुमान लगा सकते हैं। ऐसा इसलिए है क्योंकि यह जानता है कि आप उन्हें किस कार्य को पास करते हैं; अगर मेरे पास phi :: Integer -> Integer फ़ंक्शन है, और मैं phi 0 पर कॉल करता हूं, हास्केल जानता है कि वह विशेष 0Integer होना चाहिए। यह भी ठीक है अगर मैं को pho 0 के साथ फ़ंक्शनकॉल करता हूं; कि विशेष 0 को Int होने का अनुमान है।

हालांकि Int और Integer विभिन्न प्रकार हैं, और वहाँ कोई रास्ता नहीं एक विशेष 0phi और pho दोनों को पारित किया जा सकता है।

आपकी समस्या यह है कि maxRatio सौदों के साथ टपल्स टाइप किए गए हैं (0) द्वारा आप (Int, Int, Double), लेकिन यह एक ऐसा टुपल (n, phi n, ratio) के रूप में बनाया गया है। चूंकि phiInteger लेता है और देता है, उस अभिव्यक्ति में nInteger होना चाहिए। लेकिन फिर यह maxRatio के लिए काम नहीं करता है, इसलिए आपको त्रुटि मिलती है।

जो टाइप आप वास्तव में चाहते थे (Int या Integer) पर निर्भर करता है, तुम सब करने की जरूरत है phi या maxRatio के प्रकार के हस्ताक्षर इतना है कि वे संख्या का एक ही प्रकार के साथ काम कर रहे हैं बदल रहा है। हास्केल यह तय करेगा कि आपका शाब्दिक रूप से लिखा गया 0 एस उस काम को करने के लिए जो भी संख्यात्मक प्रकार आवश्यक है, प्रदान किया गया एक ऐसा है जो इसे काम कर सकता है!

ध्यान दें कि त्रुटि संदेश भेजा विशेष रूप से तुमसे कहा था कि यह (n, phi n, ratio) में n था कि एक Int होने की उम्मीद थी और वास्तव में एक Integer था। (0, 0, 0.0) टुपल का कभी भी उल्लेख नहीं किया गया है।अक्सर टाइप त्रुटियां कहीं और होती हैं जहां संकलक आपको इंगित करता है (चूंकि सभी कंपाइलर ऐसा कर सकते हैं कि अनुमान के विभिन्न श्रृंखलाएं किसी प्रकार के प्रकार पर असंगत आवश्यकताओं का उत्पादन करती हैं, इस बात का कोई तरीका नहीं है कि पूरी प्रक्रिया का कौन सा हिस्सा "गलत" है), लेकिन इस मामले में यह बहुत अच्छा किया।

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

+0

स्पष्ट स्पष्टीकरण के लिए धन्यवाद। मैंने सोचा कि '0' इसके प्रकार में पॉलिमॉर्फिक था, लेकिन मेरी नोब आंखों को प्रकार के अनुमान के लिए कोई अन्य कारण नहीं दिख रहा था जिससे त्रुटि मिली। बेशक, मैंने बस 'maxRatio' के लिए मेरी स्पष्ट प्रकार की घोषणा को याद किया। –

4

n, maxRatio के प्रकार की वजह से Int के रूप में अनुमान लगाया जा रहा है, जबकि phi के प्रकार कहते हैं कि यह Integer होना चाहिए। सबसे आसान फिक्स maxRatio के प्रकार को Integer या यहां तक ​​कि केवल a का उपयोग करने के लिए बदलना है क्योंकि यह उन मानों को स्पर्श नहीं करता है।

+0

दोह! मुझे वह जानकारी याद आई। मैं कुछ कोड को फिर से देख रहा हूं जिसे मैंने लगभग थोड़ी देर पहले लिखा था इससे पहले कि मैंने लगभग पूरी तरह से इंटीजर का उपयोग करना सीखा। –

3

यह अनुमान लगाया जा रहा है, इसलिए आप maxRatio के प्रकार हस्ताक्षर को बदल सकते हैं। फिर भी, अगर तुम कभी एक Integer का सुस्पष्ट Int बदलने की जरूरत है, toInteger :: (Integral a) => a -> Integer

+0

मैं आमतौर पर 'से इंटेगरल' का उपयोग करता हूं, खासकर जब मैं 'लंबाई' का उपयोग कर रहा हूं। 'ToInteger' की बजाय' से इंटेग्रल 'का उपयोग करने के बीच कोई अंतर है? –

+0

@ कोड-गुरु: मुझे लगता है कि केवल अंतर यह है कि 'से इंटग्रल' किसी भी 'न्यू' प्रकार को वापस कर सकता है, इसलिए इसे पढ़ने के दौरान यह थोड़ा कम स्पष्ट होता है कि किस प्रकार इसका अनुमान लगाया जा रहा है। – amindfv

+1

@ कोड-गुरु: असल में, 'इंटेग्रल' से 'इंटेग्रल = से इंटेगर' के रूप में परिभाषित किया गया है। toInteger' - तो यह निश्चित रूप से लचीलापन और पठनीयता के बीच सिर्फ एक व्यापार है – amindfv

1

आपके प्रकार के हस्ताक्षर असंगत हैं - को Integer के साथ प्रतिस्थापित करें।

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