2011-06-19 11 views
72

में एक्सपोनेंटिएशन क्या कोई मुझे बता सकता है कि हास्केल प्रीलूड एक्सपोनेंटिएशन के लिए दो अलग-अलग कार्यों को परिभाषित क्यों करता है (यानी ^ और **)? मैंने सोचा कि टाइप सिस्टम इस तरह के नकल को खत्म करना था। (^), (^^) और (**):हास्केल

Prelude> 2^2 
4 
Prelude> 4**0.5 
2.0 

उत्तर

107

वास्तव में तीन घातांक ऑपरेटरों रहे हैं। ^ है गैर नकारात्मक अभिन्न घातांक, ^^ पूर्णांक घातांक है, और ** फ्लोटिंग प्वाइंट घातांक है:

(^) :: (Num a, Integral b) => a -> b -> a 
(^^) :: (Fractional a, Integral b) => a -> b -> a 
(**) :: Floating a => a -> a -> a 

कारण टाइप है सुरक्षा: संख्यात्मक आपरेशन के परिणामों को आम तौर पर इनपुट तर्क के रूप में एक ही प्रकार है (रों) । लेकिन आप Int को फ़्लोटिंग-पॉइंट पावर में नहीं बढ़ा सकते हैं और Int प्रकार का परिणाम प्राप्त कर सकते हैं। और इसलिए टाइप सिस्टम आपको ऐसा करने से रोकता है: (1::Int) ** 0.5 एक प्रकार की त्रुटि उत्पन्न करता है। यह (1::Int) ^^ (-1) के लिए जाता है।

एक और तरीका यह डाल करने के लिए: Num प्रकार ^ के तहत बंद हो जाती हैं (वे एक गुणक उलटा करने के लिए आवश्यक नहीं कर रहे हैं), Fractional प्रकार ^^ के तहत बंद हो जाती हैं, Floating प्रकार ** के तहत बंद हो जाती हैं। चूंकि Int के लिए कोई Fractional उदाहरण नहीं है, इसलिए आप इसे नकारात्मक शक्ति में नहीं बढ़ा सकते हैं।

आदर्श रूप से, ^ का दूसरा तर्क सांख्यिकीय रूप से गैर-नकारात्मक होने के लिए बाध्य होगा (वर्तमान में, 1^(-2) रन-टाइम अपवाद फेंकता है)। लेकिन Prelude में प्राकृतिक संख्याओं के लिए कोई प्रकार नहीं है।

8

यह दो ऑपरेटरों को परिभाषित नहीं करता है - यह तीन को परिभाषित करता है! रिपोर्ट से:

तीन दो तर्क घातांक संचालन कर रहे हैं: (^) ग़ैर-ऋणात्मक पूर्णांक सत्ता में किसी भी संख्या, (^^) को जन्म देती है किसी भी पूर्णांक सत्ता में एक भिन्नात्मक संख्या को जन्म देती है, और (**) दो चल लेता है -पॉइंट तर्क। x^0 या x^^0 का मान शून्य से समेत x के लिए 1 है; 0**y अपरिभाषित है।

इसका मतलब यह है तीन अलग अलग एल्गोरिदम, जबकि ** अनुमानित परिणाम देता है जिनमें से दो, सटीक परिणाम (^ और ^^) दे रहे हैं। कौन सा ऑपरेटर उपयोग करने के लिए चुनकर, आप चुनते हैं कि कौन से एल्गोरिदम का आह्वान करना है।

4

^ एक Integral होने के लिए अपने दूसरे तर्क की आवश्यकता है। अगर मुझे गलत नहीं लगता है, तो कार्यान्वयन अधिक कुशल हो सकता है यदि आप जानते हैं कि आप एक अभिन्न एक्सपोनेंट के साथ काम कर रहे हैं। इसके अलावा, अगर आप 2^(1.234) जैसे कुछ चाहते हैं, भले ही आपका आधार एक अभिन्न है, 2, आपका परिणाम स्पष्ट रूप से fractional होगा। आपके पास अधिक विकल्प हैं ताकि आप अपने एक्सपोनिएशन फ़ंक्शन में किस प्रकार और बाहर जा रहे हैं, इस पर अधिक कड़े नियंत्रण हो सकते हैं।

हास्केल के प्रकार प्रणाली इस तरह के सी, पायथन के, या लिस्प के रूप में अन्य प्रकार प्रणाली, के रूप में एक ही लक्ष्य नहीं है। बतख टाइपिंग (लगभग) हास्केल मानसिकता के विपरीत है।

+4

मैं पूरी तरह से सहमत नहीं हूं कि हास्केल प्रकार मानसिकता बतख टाइपिंग के विपरीत है। हास्केल प्रकार के वर्ग बतख टाइपिंग की तरह काफी हैं। 'क्लास डक जहां क्वाक :: ए -> क्वाक' परिभाषित करता है कि हम बतख की अपेक्षा करते हैं, और फिर प्रत्येक इंस्टेंस कुछ ऐसा निर्दिष्ट करता है जो बतख जैसा व्यवहार कर सकता है। – augustss

+7

@augustss मैं देखता हूं कि आप कहां से आ रहे हैं। लेकिन बतख टाइपिंग के पीछे अनौपचारिक आदर्श वाक्य "अगर यह एक बतख जैसा दिखता है, एक बतख की तरह काम करता है, और एक बतख की तरह quacks, तो यह एक बतख है।" हास्केल में यह एक बतख नहीं है जब तक कि इसे 'डक' का उदाहरण घोषित न किया जाए। –

+1

यह सच है, लेकिन मैं यही है कि मैं हास्केल से अपेक्षा करता हूं। आप कुछ भी कर सकते हैं जिसे आप बतख चाहते हैं, लेकिन आपको इसके बारे में स्पष्ट होना चाहिए। हम ऐसी गलती नहीं करना चाहते हैं जिसे हमने बतख के लिए नहीं कहा था। – augustss

26

हास्केल के प्रकार प्रणाली पर्याप्त शक्तिशाली एक के रूप में तीन घातांक ऑपरेटरों व्यक्त करने के लिए नहीं है।क्या तुम सच में चाहते हैं कुछ इस तरह है:

class Exp a b where (^) :: a -> b -> a 
instance (Num a,  Integral b) => Exp a b where ... -- current^
instance (Fractional a, Integral b) => Exp a b where ... -- current ^^ 
instance (Floating a, Floating b) => Exp a b where ... -- current ** 

यह वास्तव में, यदि आप बहु पैरामीटर प्रकार वर्ग एक्सटेंशन को चालू भी काम नहीं करता है क्योंकि उदाहरण चयन अधिक चतुर से हास्केल वर्तमान की अनुमति देता है की जरूरत है ।

+3

क्या इस बारे में बयान अभी भी लागू नहीं किया जा रहा है? आईआईआरसी, हैकेल के पास पहले पैरामीटर द्वारा कड़ाई से निर्धारित किए जाने के लिए बहु-पैरामीटर प्रकार वर्ग के दूसरे पैरामीटर का विकल्प है। क्या इससे परे कोई और समस्या हल नहीं हो सकती है? – RussellStewart

+1

@singular यह अभी भी सच है। पहला तर्क दूसरा निर्धारित नहीं करता है, उदाहरण के लिए, आप एक्सपोनेंट को 'Int' और' Integer' दोनों होना चाहते हैं। उन तीन उदाहरण घोषणाओं को प्राप्त करने में सक्षम होने के लिए इंस्टेंस रिज़ॉल्यूशन को बैकट्रैकिंग का उपयोग करना पड़ता है, और कोई हास्केल कंपाइलर लागू नहीं करता है। – augustss

+4

क्या _ "टाइप सिस्टम पर्याप्त शक्तिशाली नहीं है" _ तर्क अभी भी मार्च 2015 तक है? –