2011-12-28 14 views
6

मैं OCaml के लिए निम्न हास्केल कोड का अनुवाद किया गया था:रिकॉर्ड प्रकारों के लिए कोई प्रकार का कन्स्ट्रक्टर नहीं है?

data NFA q s = NFA 
{ intialState :: q 
, isAccepting :: q -> Bool 
, transition :: q -> s -> [q] 
} 

शुरू में मैं एक बहुत ही शाब्दिक अनुवाद करने की कोशिश की:

type ('q,'s) nfa = NFA of { initialState: 'q; 
          isAccepting: 'q -> bool; 
          transition: 'q -> 's -> 'q list } 

... और निश्चित रूप से इस वजह प्रकार निर्माता भाग में सिंटेक्स त्रुटि देता है , "एनएफए" की अनुमति नहीं है। यह होना चाहिए:

type ('q,'s) nfa = { initialState: 'q; 
         isAccepting: 'q -> bool; 
         transition: 'q -> 's -> 'q list } 

मुझे यह सोचने के लिए मिला कि ऐसा क्यों है। आपके पास रिकॉर्ड प्रकार के लिए प्रकार का कन्स्ट्रक्टर क्यों नहीं हो सकता है जैसा कि आप एक टुपल प्रकार (नीचे के रूप में) के लिए कर सकते हैं?

type ('q, 's) dfa = NFA of ('q * ('q->bool) * ('q -> 's -> 'q list)) 

उत्तर

15

आप रिकॉर्ड प्रकारों के लिए एक प्रकार का कन्स्ट्रक्टर क्यों चाहते हैं, सिवाय इसके कि हास्केल में आपकी आदत है?

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

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

आपके पास रिकॉर्ड प्रकार के लिए प्रकार का कन्स्ट्रक्टर क्यों नहीं हो सकता है जैसा कि आप एक टुपल प्रकार (नीचे के रूप में) के लिए कर सकते हैं?

सावधान रहें! आपके द्वारा दिखाए गए उदाहरण में कोई टुपल नहीं है, एकाधिक मानकों के साथ केवल एक योग प्रकार है। Foo of bar * bazFoo of (bar * baz) जैसा ही है: पूर्व कन्स्ट्रक्टर के दो पैरामीटर हैं, और बाद के कन्स्ट्रक्टर में केवल एक पैरामीटर है, जो एक ट्यूपल है। यह भिन्नता प्रदर्शन कारणों के लिए की जाती है (स्मृति में, दो पैरामीटर कन्स्ट्रक्टर टैग के साथ पैक किए जाते हैं, जबकि टुपल एक संकेतक पॉइंटर बनाता है)।मल्टी-पैरामीटर के बजाए टुपल्स का उपयोग थोड़ा अधिक लचीला है: आप Foo (x, y) -> ... या Foo p -> ... दोनों के रूप में मिलान कर सकते हैं, बाद में बहु-पैरामीटर कन्स्ट्रक्टर के लिए उपलब्ध नहीं है।

टुपल्स और रिकॉर्ड्स के बीच कोई असमानता नहीं है कि उनमें से कोई भी योग प्रकार के निर्माण में विशेष स्थिति नहीं रखता है, जो केवल मनमानी धर्मार्थ के रचनाकारों का योग है। उस ने कहा, कन्स्ट्रक्टर के लिए पैरामीटर प्रकार के रूप में tuples का उपयोग करना आसान है, क्योंकि tuple प्रकारों का उपयोग करने के लिए घोषित नहीं किया जाना चाहिए। उदाहरण के लिए। कुछ लोगों को है की क्षमता के लिए कहा है इस सवाल का एक विशेष (और बहुत दिलचस्प नहीं) मामले

type foo = 
    | Foo of { x : int; y : int } 
    | Bar of { z : foo list } 

बजाय वर्तमान

type foo = Foo of foo_t | Bar of bar_t 
and foo_t = { x : int; y : int } 
and bar_t = { z : foo list } 

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

पीएस: मैं यह नहीं कह रहा हूं कि हसलेल की पसंद tuples में रिकॉर्ड को खराब करने की पसंद एक बुरी बात है। एक सुविधा को दूसरे में अनुवाद करके, आप अवधारणाओं की अनावश्यकता/ओवरलैपिंग को कम करते हैं। उस ने कहा, मैं व्यक्तिगत रूप से सोचता हूं कि रिकॉर्ड में ट्यूबल को विलुप्त करना अधिक स्वाभाविक होगा (संख्यात्मक क्षेत्र के नामों के साथ, उदाहरण के लिए ओज में किया गया है)। प्रोग्रामिंग भाषा डिज़ाइन में, अक्सर "अच्छा" और "खराब" विकल्प नहीं होते हैं, केवल अलग-अलग समझौते होते हैं।

+0

"आप रिकॉर्ड प्रकारों के लिए एक प्रकार का कन्स्ट्रक्टर क्यों चाहते हैं" - आप सही हैं, वे आम तौर पर उपयोगी नहीं हैं, शायद एक मामले को छोड़कर: योग प्रकार जिसमें रिकॉर्ड्स होते हैं: {a: .. के कुछरेक्स = आरईसी 1 टाइप करें। ; बी: ..} | आरईसी 2 का {सी: ..; डी ..} ... आदि। लेकिन जैसा कि आप कहते हैं, यह काम करना आसान है। – aneccodeal

+0

"आपके द्वारा दिखाए गए उदाहरण में कोई टुपल नहीं है, केवल कई मानकों के साथ एक योग प्रकार है। बार * बाज़ का फू वही नहीं है (बार * बाज़)" धन्यवाद, यह एक पर्ची थी! – aneccodeal

+0

कुछ चीजें: 1. जब आप कहते हैं कि रिकॉर्ड "आदिम धारणा" हैं और "अपनी पहचान है", तो मुझे लगता है कि आप का मतलब है कि रिकॉर्ड ओएमएलएल में एक विशेष मामला है, एसएमएल के विपरीत, जहां वे प्रथम श्रेणी हैं। 2. प्रोग्रामर के परिप्रेक्ष्य से, जो मेमोरी लेआउट विवरणों के अज्ञेय (न्यायसंगत) हैं, वहां * रिकॉर्ड और tuples w.r.t कन्स्ट्रक्टर तर्कों के बीच एक विषमता है। आपका उदाहरण इसे प्रदर्शित करता है। 3. तर्क के रूप में रिकॉर्ड के साथ रचनाकार नामांकित तर्क के साथ रचनाकारों के समान नहीं हैं। –

2

आप इसे प्राप्त नहीं कर सकते क्योंकि भाषा इसका समर्थन नहीं करती है। यह वास्तव में प्रकार प्रणाली या डेटा प्रतिनिधित्व में एक आसान फिट होगा, लेकिन यह संकलक में एक छोटी सी अतिरिक्त जटिलता होगी, और यह नहीं किया गया है। तो हाँ, आपको कन्स्ट्रक्टर नामकरण और तर्कों का नामकरण करने के बीच चयन करना होगा।

ध्यान दें कि रिकॉर्ड लेबल नाम किसी विशेष प्रकार से बंधे हैं, इसलिए उदा। {initialState=q} टाइप ('q, 's) nfa का एक पैटर्न है; आप लेबल नाम का एक अलग प्रकार में उपयोगी रूप से पुन: उपयोग नहीं कर सकते हैं। इसलिए कन्स्ट्रक्टर का नामकरण केवल वास्तव में उपयोगी होता है जब इस प्रकार के कई कन्स्ट्रक्टर होते हैं; फिर, यदि आपके पास किसी कन्स्ट्रक्टर के लिए बहुत से तर्क हैं, तो आप तर्कों के लिए एक अलग प्रकार को परिभाषित करना पसंद कर सकते हैं।

मेरा मानना ​​है कि इस सुविधा के लिए चारों ओर एक पैच तैर रहा है, लेकिन मुझे नहीं पता कि यह नवीनतम ओकैम संस्करण या किसी भी चीज़ के लिए अद्यतित है या नहीं, और उस पैच को रखने के लिए किसी को भी आपके कोड का उपयोग करने की आवश्यकता होगी।

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

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