2011-03-25 13 views
5

मैं एक Renamer इकाई में छिपा राज्य के रूप में किया जाता है एक प्रतीक मेज से String नाम (जो श्रेणीबद्ध पहचानकर्ता का प्रतिनिधित्व करते हैं) मेरी ASTGUID साथ नाम (पूर्णांक) में बदलने के लिए एक rename समारोह लिखना चाहते हैं।क्या टाइप को बदलने के लिए SYB का उपयोग करना संभव है?

मेरे पास AST a प्रकार है जो नाम के प्रकार पर पैरामीटरकृत है। एएसटी की पत्तियों में नाम टाइप Name a के होते हैं:

data Name a = Name a 

कौन सा आसान उन्हें एक SYB ट्रांसफार्मर के साथ लक्षित करना आसान बनाता है।

पार्सर लिखा गया (संक्षिप्तता के लिए त्रुटि की संभावना अनदेखी):

parse :: String -> AST String 

और मैं rename समारोह टाइप किया जा करना चाहते हैं:

rename :: AST String -> Renamer (AST GUID) 

यह संभव SYB उपयोग करने के लिए बदलने के लिए है सभी Name StringName GUID में ट्रांसफॉर्मर के साथ है:

resolveName :: Name String -> Renamer (Name GUID) 

और c String से c GUID से अन्य सभी मूल्यों को अपने बच्चों को बदलने और उन्हें एक ही प्रकार के पैरामीटर के साथ एक ही कन्स्ट्रक्टर के साथ वापस चिपकाकर,

everywhereM फ़ंक्शन जो मैं चाहता हूं उसके करीब है, लेकिन यह केवल c a -> m (c a) और c a -> m (c b) को बदल सकता है।

data Name = StrName String 
      | GuidName GUID 

ताकि नाम बदलने टाइप किया जा जाएगा::

मेरे वापस आने समाधान (हाथ से बॉयलर-प्लेट लेखन के अलावा अन्य) AST से प्रकार पैरामीटर हटाने, और Name इस तरह परिभाषित करने के लिए है

rename :: AST -> Renamer AST 

यह everywhereM के साथ काम कर रहा है। हालांकि, यह संभावना छोड़ देगा कि AST का नाम बदलकर StrName हो सकता है। मैं औपचारिक रूप से इस तथ्य को कैप्चर करने के लिए टाइप सिस्टम का उपयोग करना चाहता था कि नाम बदलकर AST केवल GUID नाम रख सकता है।

+2

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

+0

धन्यवाद! मैंने [पेपर] पाया (http://offog.org/publications/fita200811-generics.pdf)। यह बहुत दिलचस्प लग रहा है। – pat

+0

आप 'संश्लेषण' चाहते हैं। – sclv

उत्तर

2

एक समाधान (शायद कम कुशल से आप के लिए उम्मीद कर रहे थे) अपने AST के Functor, Data और Typeable (GHC 7 शायद आप के लिए इन सभी प्राप्त कर सकते हैं) एक उदाहरण बनाने के लिए किया जाएगा तो कार्य करें:

import Data.Generics.Uniplate.Data(universeBi) -- from the uniplate package 
import qualified Data.Map as Map 

rename :: AST String -> Renamer (AST GUID) 
rename x = do 
    let names = nub $ universeBi x :: [Name String] 
    guids <- mapM resolveName names 
    let mp = Map.fromList $ zip names guids 
    return $ fmap (mp Map.!) x 

दो अंक:

  1. मैं इसे resolveName से Name बिट खत्म करने के लिए आसान है यह सोचते हैं हूँ, लेकिन मुझे लगता है यह है।
  2. आप SYB में समकक्ष कुछ के लिए universeBi स्विच कर सकते हैं, लेकिन मुझे यूनीप्लेट संस्करणों को समझना बहुत आसान लगता है।
संबंधित मुद्दे

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