2011-01-26 12 views
9

क्या कोई मूल्य कन्स्ट्रक्टर के पैरामीटर के लिए कक्षा बाधा को परिभाषित करने का कोई तरीका है?मूल्य निर्माणकर्ताओं में कक्षा की बाधाओं को निर्दिष्ट करना

कुछ इस तरह:

data Point2D = (Num a) => Point a a 

ताकि प्वाइंट किसी भी तर्क जब तक वे Num वर्ग के हैं के रूप में ले जा सकते हैं?

+0

सामान्यतः, अपनी प्रकार की बाधाओं को रखना बेहतर होता है जहां उन्हें वास्तव में आवश्यकता होती है। यह डेटा प्रकार नहीं है, लेकिन जिस तरीके से न्यू प्रकार की आवश्यकता है, इसलिए इसे वहां घोषित किया जाना चाहिए। प्रकार प्रणाली बाकी का ख्याल रखेगी। – amccausl

उत्तर

11

आप ExistentialQuantification या GADTs का उपयोग कर सकते हैं, लेकिन न ही आप जो चाहते हैं उसे करने जा रहे हैं। आप कभी भीमानों के साथ अंकगणित करने में सक्षम नहीं होंगे। सामग्री के बारे में आप सभी जानते हैं कि वे कुछ संख्या के उदाहरण हैं। आप कंपाइलर को उनके बारे में अन्य सभी जानकारी को त्यागने के लिए कह रहे हैं। इसका मतलब यह है कि आप किसी भी जानकारी को त्यागने के लिए कंपाइलर को बता रहे हैं कि Point2D मानों की एक विशेष जोड़ी एक ही प्रकार में होती है। और उस जानकारी के बिना, आप दो Point2D एस के मूल्यों पर किसी भी अंकगणित नहीं कर पाएंगे।

यह लगभग निश्चित रूप से वह नहीं है जो आप चाहते हैं। उदाहरण के लिए, आप distance फ़ंक्शन नहीं लिख सकते हैं। इस तरह के सीमित प्रकार के लिए आपके पास क्या संभव उपयोग हो सकता है? आप उनके साथ सब कुछ कर सकते हैं उनकी सामग्री को String में परिवर्तित कर सकते हैं।

संपादित करें:

मुझे लगता है कि मैं देख रहा हूँ तुम क्या करने की कोशिश कर रहे हैं। आप बस यह सुनिश्चित करना चाहते हैं कि पॉइंट 2 डी में सबकुछ एक संख्या है। मुझे नहीं लगता कि आप वास्तव में टाइप एरर चाहते हैं।

उस मामले में, मैं एक बहुत महत्वपूर्ण परिवर्तन के साथ, GADT संस्करण के साथ जाना चाहते हैं:

{-# LANGUAGE GADTs #-} 
data Point2D a where 
    Point :: (Num a) => a -> a -> Point2D a 

इस के अंतिम परिणाम है कि आप केवल एक ही के दो मूल्यों के साथ Point निर्माता का उपयोग कर सकते है संख्या का उदाहरण, लेकिन आप किस प्रकार का खोना नहीं खोते हैं। इसके अलावा, GADTs का उपयोग करने के लिए धन्यवाद, Point पर पैटर्न-मिलान आपके लिए न्यूम संदर्भ पुनर्प्राप्त करता है, जो मूल रूप से आप अपेक्षा करते हैं।

लेकिन मुझे लगता है कि यहां सबसे महत्वपूर्ण बात सामग्री के प्रकार को फेंक नहीं रही है। ऐसा करने से मूल रूप से काम करना असंभव हो जाता है।

+0

डेटा सदस्यों के लिए उदाहरण संदर्भों को पुनर्प्राप्त करना केवल तभी काम करता है जब डेटा प्रकार पर मिलान पैटर्न (या तो '(प्वाइंट ए बी) 'या रिकॉर्ड फ़ील्ड नाम' प्वाइंट {x = a, y = b}') के साथ। लेकिन क्या फील्ड एक्सेस फ़ंक्शंस के लिए यह कोई तरीका है? यही है, ''x p' 'जैसी अभिव्यक्ति के साथ' प्वाइंट' 'पी' तक पहुंचने पर। – Lii

4

हाँ, लेकिन आपको यह महसूस करना होगा कि आपकी बाधा का अर्थ सामान्य सामान्य प्रकारों से अलग है।

आमतौर पर, जैसे जेनरिक type Foo a = (a, a) में मतलब

सभी प्रकारa के लिए , Foo a के दो a के

हालांकि, अपने उदाहरण में, एक के लिए मुहावरा है कि अलग ढंग से की जरूरत है होते हैं:

कुछ के लिए ई प्रकारa, Point2D के दो a के

या

है एक प्रकार a कि Point2D इस प्रकार

के होते हैं, सामान्य प्रकार नहीं है होते हैं सार्वभौमिक (सभी प्रकार के लिए ...), लेकिन अस्तित्व (यह कुछ प्रकार मौजूद है ...)। GHC के अंतर्गत, हम extenstion

{-# ExistentialQuantification #-} 

इस article on the topic में वर्णित के रूप के माध्यम से इस अनुमति दे सकते हैं। आपका कोड, सब के बाद,

data Point2D = forall a . Num a => Point a a 
2

ज़रूर!

यह आप क्या चाहते हैं करना चाहिए:

{-# LANGUAGE GADTs #-} 

data Point2D a where 
    Point :: Num a => a -> a -> Point2D a 

p :: Num a => a -> a -> Point2D a 
p = Point 

sumP :: Point2D a -> Point2D a -> a 
sumP (Point a b) (Point c d) = a + b + c + d 

तुम भी existensials उपयोग कर सकते हैं, लेकिन तब आप उस पर मिलान पैटर्न के बाद डेटा के साथ कुछ नहीं कर सकते।

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