2011-09-17 16 views
6

क्या एक इकाई इकाई होने के लिए एक वर्ग है (यहां सही शब्दावली के बारे में सुनिश्चित नहीं है) यानी कुछ पूर्व परिभाषित मूल्य के साथ प्रकार?क्या कोई "इकाई" वर्ग है? क्या यह उपयोगी होगा?

class Unit a where 
    unit :: a 

instance Unit() where 
    unit =() 

instance Unit (Maybe a) where 
    unit = Nothing 

... सभी Monoids, MonadPlus, आदि

के लिए मैं वर्ग के लिए एक और नाम Default हो सकता है लगता है। यह मेरे लिए हाल ही में दो बार उपयोगी होगा।

शायद अपुष्ट उदाहरण:

extract :: (Unit r)=> Reader r a -> a 
extract r = runReader r unit 

इस मौजूद है? क्या दूसरों को लगता है कि यह उपयोगी हो सकता है?

उत्तर

9

हां, यह शायद उपयोगी होगा। वास्तव में, इसके सभी असंगत संस्करण उपयोगी होंगे! जो समस्या है थोड़ी सी है।

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

कुछ उदाहरण:

  • Monoid के लिए उदाहरणों, आपको स्पष्ट रूप से पहचान तत्व डिफ़ॉल्ट होने की उम्मीद थी। लेकिन अब आप दो या अधिक समझदार Monoid उदाहरण वाले कई प्रकार की समस्या पर वापस आ गए हैं। क्या डिफ़ॉल्ट Integer 0 या 1 है? Monoid के लिए, मानक लाइब्रेरी newtype रैपर का उपयोग करती है, लेकिन वे बेकार हैं और लिपटे प्रकारों के साथ काम करना मुश्किल बनाते हैं - Monoid के साथ यह ठीक काम करता है क्योंकि आपको mconcat तक पहुंच मिलती है और ऐसा नहीं है, लेकिन आप कुछ भी रोचक नहीं कर सकते सिर्फ एक डिफ़ॉल्ट मान के साथ।

  • Functor के लिए "खाली" मान वाले प्रकारों के साथ, जो एक स्पष्ट डिफ़ॉल्ट देता है। यह MonadPlus और Alternative कर रहे हैं ... और Monoid के साथ ओवरलैप भी है, और यदि स्मृति मुझे सेवा देती है तो कम से कम एक प्रकार है जहां वे तीन उदाहरण समान नहीं हैं। एक से अधिक विकल्प होने पर आप कौन सी चुनते हैं? सूचियों पर विचार करें: आप अंधेरे से उन्हें जोड़ सकते हैं, एक मनमाना Monoid, पहचान के रूप में खाली सूची के साथ; लेकिन Monoids की सूचियों के लिए आप zipWith mappend भी पहचान सकते हैं, जिससे पहचान के रूप में repeat mempty के साथ एक उठाया मोनोइड दिया जा सकता है। कई मज़ेदारों के समान Monoid उदाहरण होते हैं, लेकिन हमेशा दोनों नहीं - इसलिए जो भी आप सूचियों के लिए चुनते हैं, आप कुछ अन्य Functor के साथ अवधारणात्मक रूप से असंगत होंगे!

  • () जैसे इकाई प्रकारों के लिए, डिफ़ॉल्ट को चुनना मुश्किल नहीं है! लेकिन गणना के बारे में क्या? क्या पहले कन्स्ट्रक्टर को चुनना समझ में आता है? कभी-कभी, लेकिन हमेशा नहीं। कक्षा का उपयोग करने वाले लोग कैसे जानेंगे?

  • Bounded के बारे में क्या? यदि उपरोक्त में से कोई भी लागू नहीं होता है, तो आप minBound का उपयोग कर सकते हैं। लेकिन उपरोक्त में से कुछ प्रकार Bounded भी हो सकते हैं, इसलिए यदि आप उनका डिफ़ॉल्ट न्यूनतम मान नहीं रखते हैं तो आप मामलों को भ्रमित कर देंगे।

मूल रूप से, वहाँ सिर्फ पर्याप्त ओवरलैप है कि यह लगता समझ बनाने के लिए है ... लेकिन वास्तव में, यदि आपके मन में कम से कम तीन अलग प्रकार कक्षाएं यहाँ मिल गया है, और उन्हें एकजुट करने के लिए कोशिश कर रहा है शायद के रूप में नहीं है सहायक लगता है क्योंकि यह पहली बार लगता है।


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

यह कहा गया है कि, एक स्पष्ट रूप से समझदार मामला जो किसी भी मानक प्रकार वर्ग द्वारा कवर नहीं है, () जैसे सिंगलेट्स है। ज्यादातर समय ये बहुत उपयोगी नहीं हैं - स्पष्ट कारणों से! - शायद यही कारण है कि ऐसी कक्षा नहीं है। एक जगह जहां ऐसी कक्षा अत्यंत उपयोगी है, हालांकि, जब आप टाइप-स्तरीय शेंगेनिक्स से जुड़े कुछ कर रहे हैं, क्योंकि ऐसा प्रकार प्रकार और अवधि स्तर दोनों पर एक एकल मान का प्रतिनिधित्व करता है - इसलिए इस प्रकार के वर्ग आपको टाइप-स्तरीय मानों को स्वतंत्र रूप से कुशलतापूर्वक उपयोग करने देता है, फिर उस शब्द को स्वीकार करें जो इसके साथ जाता है, ताकि आप इसे किसी अन्य फ़ंक्शन पर पास कर सकें, उदाहरण के लिए, इसके आधार पर एक प्रकार का क्लास इंस्टेंस चुनें। यही वजह है कि मैं a class along those lines in my perpetually-incomplete type-hackery library है, उदा .:

class TermProxy t where 
    term :: t 

-- This makes explicit the lexical pun of() having type(). 
instance TermProxy() where 
    term =() 

instance (TermProxy a, TermProxy b) => TermProxy (a, b) where 
    term = (term, term) 

मुझे शक है इस तरह के एक वर्ग किसी अन्य संदर्भ में बहुत ही उपयोगी है, हालांकि है।

+0

आपके उदार उत्तर के लिए इस तरह के अस्पष्ट उत्तर के लिए धन्यवाद। मैं वास्तव में "डिफ़ॉल्ट" की धारणा में दिलचस्पी नहीं लेता हूं (संभवतः इसका उल्लेख नहीं किया जाना चाहिए था!), लेकिन इनमें से अधिक() जैसी चीजें हैं जो किसी फ़ंक्शन के बाएं हाथ पर होती हैं (या वहां के अबास्ट्रक्शन) ... मुझे इस वर्ग का उपयोग करने के तरीके के बारे में और सोचने की जरूरत है। धन्यवाद! – jberryman

+1

@ जेबरीमैन: मुझे लगता है कि आप जो भी कर रहे हैं वह एक प्रकार का वर्ग है जो वास्तव में एक नलिका कन्स्ट्रक्टर के साथ है? जिसमें '()', 'कुछ भी नहीं', '[] ', आदि शामिल होगा।, लेकिन बुलियन या संख्या या ऐसा कुछ भी नहीं। यह कम से कम स्पष्ट रूप से परिभाषित किया गया है और एकल अकेले अकेले के रूप में छोटा नहीं है। –

+0

हाँ, यह सही है। मेरे 'रीडर' उदाहरण की तर्ज पर, मैं यह खोज रहा हूं कि सिंक या फ़ंक्शंस या अन्यथा कॉफ़नक्टर-आईएसएच के प्रकार, मैं विशेष मामले '()' के लिए दिलचस्प कार्यों को परिभाषित कर सकता हूं, उदा। 'liftCofunc :: (कोफंक्टर एफ) => एफ() -> एफ ए'। मैंने सोचा कि यह देखना दिलचस्प हो सकता है कि ऊपर दिया गया कार्य अधिक सामान्य रूप से परिभाषित किया जा सकता है या नहीं। एक बार फिर धन्यवाद। * संपादित करें *: मुझे लगता है कि यह शायद एक संयोग नहीं है कि 'कोफंक्टर' मानक वर्ग भी नहीं है;) – jberryman

6

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

वर्ग है:

unit :: Enum a => a 
unit = toEnum 0 

या हो सकता है घिरा वर्ग के साथ बेहतर:

-- | A class for types with a default value. 
class Default a where 
    -- | The default value for this type. 
    def :: a 
+0

बहुत बहुत धन्यवाद। जैसा कि मैंने सीए को टिप्पणी की थी। मैककन, यह "डिफ़ॉल्ट" होने की धारणा एक विचार के बाद थी और मुझे – jberryman

+2

हाँ करने की कोशिश कर रहा है, इसके बारे में अच्छी सोच होनी चाहिए, कि 'डिफ़ॉल्ट' वर्ग सुसंगत है जैसा कि आप उम्मीद कर सकते हैं। इसमें अभी भी कुछ अंतर्निहित भ्रम है जिसका मैंने उल्लेख किया है - उदाहरण के लिए, कुछ 'मोनाड' उदाहरण 'रिटर्न डीफ़' हैं, जबकि अन्य नहीं हैं। तो किसी संदर्भ के साथ कोई भी कार्य '(मोनाड एम, डिफ़ॉल्ट एम ए) =>' अलग-अलग 'मोनाद' के लिए बहुत अलग व्यवहार करने जा रहा है। –

+2

मुझे 'डेटा-डिफ़ॉल्ट' विशेष रूप से कॉन्फ़िगरेशन संरचनाओं के लिए उपयोगी लगता है और इसी तरह, जहां एक अनुप्रयोग के संदर्भ में एक समझदार डिफ़ॉल्ट मौजूद है। इसके अलावा उदाहरण निर्यात नहीं किए जाते हैं। –

3

आप एक नया वर्ग से बचना चाहते हैं, तो आप Enum वर्ग के संदर्भ में इकाई को परिभाषित कर सकते हैं:

unit :: Bounded a => a 
unit = minBound 

इन दोनों इकाई प्रकार के लिए उम्मीद परिणाम उपज (और किसी भी अन्य एकल चोर के लिए सबसे अधिक संभावना structor प्रकार):

*Main> unit ::() 
() 

डेटा-डिफ़ॉल्ट वर्ग (एक और जवाब में बताया गया की तुलना में कमियां) कम उदाहरणों, विशेष रूप से कोई उदाहरण [एक] के लिए [] रिटर्न कि देखते हैं कि है। नतीजा यह नहीं है कि आप किसी प्रकार से क्या उम्मीद कर सकते हैं, खासकर यदि आप मिनीबाउंड का उपयोग करते हैं:

*Main> unit :: Int 
-2147483648 

*Main> unit :: Char 
'\NUL' 

*Main> unit :: Bool 
False 
संबंधित मुद्दे