2013-01-09 10 views
5

पर विचार करें निम्नलिखित दो प्रकार:विभिन्न नाम रिक्त स्थान में हैकेल फ़ील्ड नाम कैसे रखें?

data Point=Point{x::Float,y::Float} 
data Rectangle = {upperLeft::Point, bottomRight::Point} 
data Square = {upperLeft::Point, bottomRight::Point} 

GHC संकलक शिकायत है कि वर्ग के साथ आयत संघर्ष में upperLeft फ़ील्ड नाम। यह अजीब लगता है कि इसके चेहरे पर प्रत्येक फ़ील्ड का नाम इस प्रकार के नामस्थान में होना चाहिए, अन्यथा कोई फ़ील्ड नामों का पुन: उपयोग नहीं कर सकता है, और मुझे संदेह है कि यह काफी आम उम्मीद होगी। इस से

let a=Rectangle{upperLeft=Point 2 3, bottomRight=Point 7 7} 
let a=Square{upperLeft=Point 2 3, bottomRight=Point 7 7} 

हम चाहते हैं कि हम उम्मीद करते हैं कि प्रत्येक फ़ील्ड नाम उनके संबंधित प्रकार नाम स्थान के भीतर होना चाहिए सक्षम होना चाहिए देख सकते हैं:

उदाहरण एक चर हम लिख परिभाषित करने के लिए के लिए

क्या मेरा उपयोग सही है या मेरी अपेक्षाएं गलत हैं? क्या इसे ठीक करने के लिए कोई रास्ता है?

उत्तर

3

हास्केल में, एक रिकॉर्ड प्रकार बनाने से भी एक्सेसर फ़ंक्शन बनते हैं। उदाहरण के लिए, आप चला सकते हैं: x (upperLeft a) ऊपर दिए गए चरों में से किसी एक पर 2. यहां summary of record syntax है।

आप विकल्प या तो रिकॉर्ड पर विभिन्न फ़ील्ड नामों का उपयोग करने या उन्हें अलग मॉड्यूल में रखने के लिए हैं। चूंकि मॉड्यूल में प्रत्येक का अपना नाम स्थान होता है, यदि आप आयत मॉड्यूल में स्क्वायर मॉड्यूल और आयत में स्क्वायर डालते हैं, तो आप फ़ील्ड नामों का पुन: उपयोग करने में सक्षम होंगे।

+1

प्रत्येक प्रकार को अपने मॉड्यूल में रखते हुए एक ओवरकिल लगता है। मुझे एहसास हुआ कि एक्सेसर फ़ंक्शंस बनाए गए थे, लेकिन मैं उम्मीद कर रहा था कि टाइप अनुमान का उपयोग करने के लिए सही फ़ील्ड नाम का चयन होगा। –

+0

हां, मैं मानता हूं कि इस मामले में मॉड्यूल में अलग होने से ओवरकिल लगता है। मैं शायद फ़ील्ड नामों को बदल दूंगा। 'RectUpperLeft 'की तरह कुछ' ऊपरी स्तर 'से अधिक लंबा नहीं है। मैं मानता हूं कि फील्ड नामों का पुन: उपयोग करना उपयोगी और उचित चीज़ की अपेक्षा करता है, लेकिन जहां तक ​​मुझे पता है, आप बस हास्केल के रिकॉर्ड के साथ ऐसा नहीं कर सकते हैं। – astrieanna

2

आप आयताकार प्रकार में स्क्वायर कन्स्ट्रक्टर डालने से दूर हो सकते हैं क्योंकि यह वास्तव में उस प्रकार का एक विशेषज्ञ है। के बाद से यह कुछ कमी है

upperLeft s 
upperLeft r 

आप स्क्वायर बदलने के लिए चाहते हो सकता है हालांकि:

data Point 
    = Point{x::Float,y::Float} 
    deriving (Eq, Show) 

data Rectangle 
    = Rectangle {upperLeft::Point, bottomRight::Point} 
    | Square {upperLeft::Point, bottomRight::Point} 
    deriving (Eq, Show) 

let r = Rectangle (Point 3.0 4.0) (Point 4.0 2.0) 
let s = Square (Point 2.0 4.0) (Point 4.0 2.0) 

तो फिर तुम दोनों कॉल कर सकते हैं:

GHCi में बाहर सामान टाइपिंग से, इस अच्छा काम करने लगता है इसे पूरा करना होगा:

data Rectangle 
    = Rectangle {upperLeft::Point, bottomRight::Point} 
    | Square {upperLeft::Point, size::Float} 
    deriving (Eq, Show) 
4

चूंकि ऑब्जेक्ट्स को उनके फील्ड नामों के माध्यम से एक्सेस किया जा सकता है, सह mpiler किसी ऑब्जेक्ट के प्रकार को अपने फ़ील्ड नाम से अनुमानित करने में सक्षम होना चाहिए। उदाहरण के लिए,

boundingBox x = bottomRight x - upperLeft x 

accessors bottomRight और upperLeft में x के प्रकार के अनुमान लगाने के लिए किया जाता है। यदि एकाधिक प्रकारों को एक ही एक्सेसर नाम रखने की अनुमति थी, तो प्रकार का अनुमान लगाना संभव नहीं होगा।

नाम टकराव से बचने के लिए, एक आम सम्मेलन सभी फ़ील्ड नामों पर उपसर्ग डालना है। इस सम्मेलन का प्रयोग जीएचसी परियोजना में किया जाता है।

data Rectangle = {rc_upperLeft :: Point, rc_bottomRight :: Point} 
data Square = {sq_upperLeft :: Point, sq_bottomRight :: Point}