2011-09-15 8 views
6

मैं लगभग एक महीने तक हास्केल के साथ खेल रहा हूं। मेरे पहले "असली" हास्केल प्रोजेक्ट के लिए मैं एक भाग-भाषण टैगर लिख रहा हूं।

data Tag = CC | CD | DT | EX | FW | IN | JJ | JJR | JJS ... 

से ऊपर है मानकीकृत भागों के- भाषण टैग जो मैंने की एक लंबी सूची: इस परियोजना के हिस्से के रूप में मैं इस प्रकार के रूप में लागू एक प्रकार Tag कहा जाता है कि एक भागों के- भाषण टैग का प्रतिनिधित्व करता है, जानबूझकर छंटनी हालांकि, टैग के इस मानक सेट में दो डॉलर हैं जो डॉलर के चिह्न ($) में समाप्त होते हैं: पीआरपी $ और एनएनपी $। क्योंकि मेरे पास उनके नाम पर $ के साथ टाइप कन्स्ट्रक्टर नहीं हो सकते हैं, इसलिए मैंने उन्हें पीआरपीएस और एनएनपीएस का नाम बदलने के लिए चुना है।

यह सब ठीक है और अच्छा है, लेकिन मैं एक लेक्सिकॉन में तारों से टैग पढ़ना चाहता हूं और उन्हें अपने Tag प्रकार में परिवर्तित करना चाहता हूं। इस कोशिश कर रहा है विफल रहता है:

instance Read Tag where 
    readsPrec _ input = 
     (\inp -> [((NNPS), rest) | ("NNP$", rest) <- lex inp]) input 

हास्केल lexer $ पर chokes। कोई विचार यह कैसे खींचें?

कार्यान्वयन शो काफी सरल था। अगर पढ़ने के लिए कुछ समान रणनीति थी तो यह बहुत अच्छा होगा।

instance Show Tag where 
    showsPrec _ NNPS = showString "NNP$" 
    showsPrec _ PRPS = showString "PRP$" 
    showsPrec _ tag = shows tag 
+2

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

उत्तर

5

आप यहां Read का दुरुपयोग कर रहे हैं।

Show और Read प्रिंट और पार्स वैध हास्केल मूल्यों, डिबगिंग को सक्षम करने के लिए के लिए होती हैं, आदि यह नहीं हमेशा पूरी तरह से (उदाहरण के लिए यदि आप Data.Map योग्य और फिर आयात fromList प्रतिसाद नहीं करने के लिए एक Map मूल्य पर show फोन कॉल योग्य नहीं है) लेकिन यह एक वैध प्रारंभिक बिंदु है।

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

जबकि आप तर्क दे सकते हैं कि यह आवश्यक नहीं है, यह सिर्फ एक त्वरित 'हैकडी हैक है जो आप कर रहे हैं, जल्दी से ग़लत हैक के पास घूमने की प्रवृत्ति है ... अपने आप को एक पक्ष बनाओ और इसे पहली बार सही करें: इसका मतलब है कि जब आप इसे "ठीक से" करना चाहते हैं तो फिर से लिखना कम है।

+0

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

+0

विशेष रूप से, 'रीड' और 'शो' का उद्देश्य' स्ट्रिंग 'से और उसके लिए खराब व्यक्ति के क्रमिकरण/deserialization का एक मिलान सेट होना है, अतिरिक्त धारा के साथ, धारावाहिक रूप, अगर मूल स्रोत फ़ाइल में कट और पेस्ट करें, तो एक 'शो' के बराबर मान का प्रतिनिधित्व किया गया था। –

4

तब हास्केल लेक्सर का उपयोग न करें। read फ़ंक्शंस ParSec का उपयोग करते हैं, जिन्हें आप रियल वर्ल्ड हास्केल पुस्तक में उत्कृष्ट परिचय प्राप्त कर सकते हैं।

यहाँ कुछ कोड काम करने के लिए लगता है कि,

import Text.Read 
import Text.ParserCombinators.ReadP hiding (choice) 
import Text.ParserCombinators.ReadPrec hiding (choice) 

data Tag = CC | CD | DT | EX | FW | IN | JJ | JJR | JJS deriving (Show) 

strValMap = map (\(x, y) -> lift $ string x >> return y) 

instance Read Tag where 
    readPrec = choice $ strValMap [ 
     ("CC", CC), 
     ("CD", CD), 
     ("JJ$", JJS) 
     ] 

सिर्फ

(read "JJ$") :: Tag 

कोड सुंदर आत्म व्याख्यात्मक है के साथ इसे चलाने के लिए है। string x पार्सर मोनैड x से मेल खाता है, और यदि यह सफल होता है (अपवाद फेंकता नहीं है), तो y वापस कर दिया गया है। हम इन सभी में से चुनने के लिए choice का उपयोग करते हैं। यह उचित रूप से बैकट्रैक करेगा, इसलिए यदि आप CCC कन्स्ट्रक्टर जोड़ते हैं, तो CC आंशिक रूप से मिलान "सीसीसी" बाद में विफल हो जाएगा, और यह CCC पर वापस आ जाएगा। बेशक, अगर आपको इसकी आवश्यकता नहीं है, तो <|> संयोजक का उपयोग करें।

+0

धन्यवाद। यह वही है जो मैं पूरा करने की कोशिश कर रहा था। – svoisen

+1

@gatoatigrado: असल में, 'रीड' फ़ंक्शंस ** नहीं ** ** पार्ससी का उपयोग करें: उनके पास अपना स्वयं का पार्सर है। – ivanm