2015-08-15 2 views
6

यह एक प्रोग्रामिंग शैली और सामान्य प्रथाओं के बारे में एक सवाल है। लेकिन मुझे लगता है कि यह कोड समीक्षा मंच में फिट नहीं है ...किसी डेटा प्रकार को अधिभारित करने या समान उपयोग करने के लिए?

मेरा प्रोग्राम नियमित अभिव्यक्तियों को पार करता है और उन्हें संसाधित करता है। रेगुलर एक्सप्रेशन सामान्य तत्वों (क्लीन बंद, संयोजन, आदि) हो सकता है और यह भी, उनके नाम से अन्य नियमित अभिव्यक्ति के लिए संदर्भ हो सकता है मैक्रो की तरह:

data Regex a = Epsilon 
      | Literal a 
      | Ranges [(a, a)] 
      | Ref String 
      | Then (Regex a) (Regex a) 
      | Or (Regex a) (Regex a) 
      | Star (Regex a) 

मैं रेगुलर एक्सप्रेशन संसाधित होने के बाद और सभी मैक्रो को हल

: संदर्भ, और Range तत्वों को Literal तत्वों परिवर्तित (यह मेरी प्रयोजनों के लिए की जरूरत है), मैं एक प्रकार है कि नहीं और Ref और Literal नहीं होना चाहिए कर सकते हैं के साथ खत्म हो, मेरे कार्यों कि इसके साथ काम में तो मैं कुछ पसंद है
foo (Literal _) = error "unexpected literal" 
foo (Ref _)  = error "unexpected reference" 
foo (Epsilon) = ... 
foo (Star x) = ... 
... 

यह बदसूरत दिखता है मुझे क्योंकि यह संकलन के दौरान चेक के बजाय रनटाइम चेक करता है। एक बहुत ही तरह की दृष्टिकोण नहीं है।

तो शायद मैं एक और डेटा प्रकार पेश कर सकता हूं जो मूल के समान है और इसका उपयोग करता है?

data RegexSimple a = Epsilon2 
        | Ranges2 [(a, a)] 
        | Then2 (Regex a) (Regex a) 
        | Or2 (Regex a) (Regex a) 
        | Star2 (Regex a) 

काम यही है, लेकिन यहाँ मैं दोहराव के लिए बहुत कुछ है और यह भी निर्माताओं की अच्छी और वर्णनात्मक नाम अब लिया जाता है और मैं नए आविष्कार करने की जरूरत है ...

विशेषज्ञों क्या करना होगा यहाँ? मैं सीखना चाहता हूं:)

+0

क्या आपने [GADTs] को देखा है (https: // en।wikibooks.org/wiki/Haskell/GADT)? – Kwarrtz

+0

बस यह इंगित करना चाहते हैं कि आप "समान" कन्स्ट्रक्टर नामों के साथ दूसरे डेटा प्रकार का उपयोग कर सकते हैं यदि आप इसे किसी भिन्न मॉड्यूल में परिभाषित करते हैं। फिर आप 'आयात योग्य ... जैसे ...' का उपयोग कर सकते हैं यदि कुछ कोड दोनों प्रकारों से निपटने की ज़रूरत है। – ErikR

+1

'डेटा प्रकार ए ला कार्टे' http://www.cs.ru.nl/~W.Swierstra/Publications/DataTypesALaCarte.pdf –

उत्तर

5

मैं अपने कोड के बाकी की तरह दिखता है क्या पता नहीं है, इसलिए यह समाधान आपको कुछ पहलुओं पर पुनर्विचार करने की आवश्यकता हो सकती है, लेकिन इस समस्या का सबसे "हास्केल-ish" समाधान शायद GADTs और phantom types उपयोग करने के लिए किया जाएगा। साथ में, वे मूल रूप से आपको अधिक लचीली प्रकार की सुरक्षा के लिए मनमाने ढंग से उपप्रकार बनाने की अनुमति देते हैं। आप अपने प्रकारों को फिर से परिभाषित करेंगे।

{-# LANGUAGE GADTs #-} 

data Literal 
data Ref 
data Rangeable 

data Regex t a where 
     Epsilon :: Regex Rangeable a 
     Literal :: a -> Regex Literal a 
     Ranges :: [(a, a)] -> Regex Rangeable a 
     Ref  :: String -> Regex Ref a 
     Then :: Regex t' a -> Regex t' a -> Regex Rangeable a 
     Or  :: Regex t' a -> Regex t' a -> Regex Rangeable a 
     Star :: Regex t' a -> Regex Rangeable 

तो फिर तुम

foo :: Regex Rangeable a 
foo (Epsilon) = ... 
foo [email protected](Star a) = ... 

अब परिभाषित कर सकते हैं, foo $ Literal 'c' जैसे बयानों संकलन समय प्रकार-जांच असफल हो जायेगी।

+0

पर भी एक नज़र डालें। यह बहुत अच्छा है। मैंने पहले कभी इस तकनीक को नहीं देखा है। क्या इसके बारे में कोई संसाधन है? – mb14

+0

मेरे उत्तर में शामिल लिंक पर एक नज़र डालें ([यह] (https://en.wikibooks.org/wiki/Haskell/GADT)) – Kwarrtz

+0

@Kwarrtz धन्यवाद यह काम करता है हालांकि मुझे अपने ' फिर, 'ओ'',' स्टार', 'ईपीएसलॉन' सामान्य मामले में: 'रेगेक्स टी' ए -> रेगेक्स टी 'ए -> रेगेक्स टी' ए', आदि। क्योंकि मुझे उन सभी उप-प्रकारों में आवश्यकता है। – akonsu

2

मैं एक विशेषज्ञ नहीं हूं लेकिन यह एक समस्या है जो मेरे पास भी है (भले ही यह उत्पाद प्रकार के साथ अधिक प्रकार के हो)।

स्पष्ट समाधान ताकि

data Regex a = Ref a | Literal a | SimpleR (SimpleRegex a) 

एक और तरीका एक functor

data Regex f a = Literal (f a) | Ref (f a) | Epsilon a ... 

साथ Regex parametrize और या तो Regex Id या Regex Void उपयोग करने के लिए है Regex में RegexSimple पुन: उपयोग किया जा सके।

एक और तरीका है बस Maybe

data Regex a = Literal (Maybe a) | Epsilon a ... 

उपयोग करने के लिए लेकिन यह यह कम साफ है क्योंकि आप करने के लिए एक समारोह लागू नहीं कर सकते केवल सरल regex स्वीकार है।

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

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