2012-06-19 26 views
15

क्यों नहीं है मैं एक हास्केल नौसिखिया हूं। मैं देखा है कि हास्केल रिकॉर्ड नाम से अधिक भार का समर्थन नहीं करता:हास्केल/जीएचसी समर्थन रिकॉर्ड नाम ओवरलोडिंग

-- Records.hs 

data Employee = Employee 
    { firstName :: String 
    , lastName :: String 
    , ssn :: String 
    } deriving (Show, Eq) 

data Manager = Manager 
    { firstName :: String 
    , lastName :: String 
    , ssn :: String 
    , subordinates :: [Employee] 
    } deriving (Show, Eq) 

जब मैं इस संकलन मैं:

[1 of 1] Compiling Main    (Records.hs, Records.o) 

Records.hs:10:5: 
    Multiple declarations of `firstName' 
    Declared at: Records.hs:4:5 
       Records.hs:10:5 

Records.hs:11:5: 
    Multiple declarations of `lastName' 
    Declared at: Records.hs:5:5 
       Records.hs:11:5 

Records.hs:12:5: 
    Multiple declarations of `ssn' 
    Declared at: Records.hs:6:5 
       Records.hs:12:5 

को देखते हुए हास्केल प्रकार प्रणाली की "शक्ति", ऐसा लगता है जैसे कि यह होना चाहिए संकलक के लिए यह निर्धारित करने के लिए कि

emp = Employee "Joe" "Smith" "111-22-3333" 
man = Manager "Mary" "Jones" "333-22-1111" [emp] 
firstName man 
firstName emp 

क्या कोई समस्या है जिसे मैं नहीं देख रहा हूं। मुझे पता है कि हास्केल रिपोर्ट इसकी अनुमति नहीं देती है, लेकिन क्यों नहीं?

+1

यह आपके प्रश्न का उत्तर नहीं है, लेकिन जब भी आपकी जैसी स्थिति उत्पन्न होती है तो मैं डेटा प्रकारों को अलग-अलग मॉड्यूल में विभाजित करता हूं। उदाहरण के लिए, मैं 'कर्मचारी' मॉड्यूल और 'प्रबंधक' मॉड्यूल बना सकता हूं, और उन्हें क्रमशः 'ई' और' एम' के रूप में योग्यता आयात कर सकता हूं, और फिर 'ई। फर्स्टनाम', 'एम। फर्स्टनाम' आदि का उपयोग कर सकता हूं। यह मुझे उचित रूप से अच्छा वाक्यविन्यास देता है। (मैं यह नहीं कह रहा हूं कि यह एक अच्छा विचार है, लेकिन यह वही है जो मैंने कर लिया है और यह मेरे मामलों में अच्छी तरह से निकला है)। – gspr

+3

हाँ, लेकिन यह एक अन्यथा सुरुचिपूर्ण भाषा में "क्लेज" जैसा लगता है। – Ralph

उत्तर

15

ऐतिहासिक कारण। Haskell के लिए बेहतर रिकॉर्ड सिस्टम के लिए have beenmany competing designs - वास्तव में बहुत से, no consensus तक पहुंचा जा सकता है। फिर भी।

9

वर्तमान रिकॉर्ड सिस्टम बहुत परिष्कृत नहीं है। यदि रिकॉर्ड रिकॉर्ड सिंटैक्स नहीं था तो यह बॉयलरप्लेट के साथ चीजों के लिए ज्यादातर सिंटैक्टिक चीनी है।

विशेष रूप से, इस:

data Employee = Employee 
    { firstName :: String 
    , lastName :: String 
    , ssn :: String 
    } deriving (Show, Eq) 

(अन्य बातों के अलावा) एक समारोह firstName :: Employee -> String उत्पन्न करता है।

आप भी इस प्रकार एक ही मॉड्यूल में अनुमति देते हैं:

data Manager = Manager 
    { firstName :: String 
    , lastName :: String 
    , ssn :: String 
    , subordinates :: [Employee] 
    } deriving (Show, Eq) 

तो क्या firstName समारोह के प्रकार हो सकता है?

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

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

+0

मुझे लगता है कि आप एक टाइपक्लास बना सकते हैं और उसके बाद टाइपक्लास विधियां विशिष्ट रिकॉर्ड संस्करणों को कॉल कर सकती हैं, लेकिन इससे ऐसी भाषा में बहुत सारे बॉयलरप्लेट जोड़े जाएंगे जो आमतौर पर इसकी आवश्यकता नहीं होती है। – Ralph

+1

यदि आप फ़ील्ड ओवरलोडिंग की अनुमति देते हैं, तो 'firstName' फ़ंक्शन में 'forall' टाइप होना चाहिए। A'। टाइप अनुमान या स्पष्ट प्रकार की घोषणा के साथ इस प्रकार को विशिष्ट होना चाहिए। Agda में रिकॉर्ड निर्माता इस तरह काम करता है। – JJJ

4

इससे बचने का एक विकल्प है अपने डेटा प्रकार को विभिन्न मॉड्यूल में रखना और योग्य आयात का उपयोग करना। इस तरह आप अलग-अलग डेटा रिकॉर्ड्स पर उसी फ़ील्ड एक्सेसर्स का उपयोग कर सकते हैं और आपको कोड को साफ और अधिक पठनीय रख सकते हैं।

आप उदाहरण

module Model.Employee where 

data Employee = Employee 
    { firstName :: String 
    , lastName :: String 
    , ssn :: String 
    } deriving (Show, Eq) 

और प्रबंधक के लिए एक मॉड्यूल, उदाहरण के लिए के लिए कर्मचारी के लिए एक मॉड्यूल बना सकते हैं,:

module Model.Manager where 

import Model.Employee (Employee) 

data Manager = Manager 
    { firstName :: String 
    , lastName :: String 
    , ssn :: String 
    , subordinates :: [Employee] 
    } deriving (Show, Eq) 

और फिर भी आप इन दो डेटा प्रकार का उपयोग करना चाहते आप उन्हें योग्यतापूर्वक आयात कर सकते हैं और उन्हें निम्नानुसार एक्सेस कर सकते हैं:

import   Model.Employee (Employee) 
import qualified Model.Employee as Employee 
import   Model.Manager (Manager) 
import qualified Model.Manager as Manager 

emp = Employee "Joe" "Smith" "111-22-3333" 
man = Manager "Mary" "Jones" "333-22-1111" [emp] 

name1 = Manager.firstName man 
name2 = Employee.firstName emp 

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