2011-03-14 13 views
6

मुझे टेम्पलेट हास्केल कोड में फ़ंक्शन डालने की आवश्यकता है। मैं अभिव्यक्ति वाक्यविन्यास का उपयोग कर रहा हूं: लिफ्ट उदाहरण?

[|f|]
कुछ फ़ंक्शन स्वचालित रूप से काम करने लगते हैं। बहरहाल, यह विशेष रूप से एक के लिए मैं निम्नलिखित erroe संदेश मिलता है:

 
    No instance for (Lift (String -> [Content])) 

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

+0

मैं [डॉक्स] पाया है (http://hackage.haskell.org/packages/archive/template-haskell/2.4.0.1/doc/html/Language-Haskell-TH: यहाँ Maybe के लिए एक है -Syntax.html # टी: लिफ्ट) (लगभग कोई नहीं)। उम्मीद है कि यह मदद करता है, लेकिन शायद यह नहीं होगा :(ऐसा लगता है कि आपको एक समारोह 'लिफ्ट :: (स्ट्रिंग -> [सामग्री]) -> क्यू एक्सप' लिखना है, यानी, अपने फ़ंक्शन को अभिव्यक्ति में अनुवादित करें। –

उत्तर

7

मैं एक स्टैब ले जाऊंगा, हालांकि TH को और कोड देखने के बिना डीबग करना मुश्किल हो सकता है।

foo.hs:

{-# Language TemplateHaskell #-} 

baz x = let f y = x + y 
    in [| f |] 

bez x = let f y = x + y 
    in [| \y -> f y |] 

boz x = [| \y -> x + y |] 

g x y = x + y 

byz x = [| g x |] 

अब हम (मैं संस्करण 7.0.2 पर हूँ, जो GHCi में इस सक्रिय कर सकता है

के कुछ नमूना कोड पर एक नज़र डालते हैं क्या वर्तमान हास्केल मंच) के साथ जहाजों:

$ ghci foo.hs -XTemplateHaskell 
*Main> :m +Language.Haskell.TH 
*Main Language.Haskell.TH> runQ (baz 2) 

<interactive>:1:7: 
No instance for (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) 
    arising from a use of `baz' 
Possible fix: 
    add an instance declaration for 
    (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) 
In the first argument of `runQ', namely `(baz 2)' 
In the expression: runQ (baz 2) 
In an equation for `it': it = runQ (baz 2) 
*Main Language.Haskell.TH> runQ (bez 2) 

<interactive>:1:7: 
    No instance for (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) 
     arising from a use of `bez' 
    Possible fix: 
     add an instance declaration for 
     (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) 
    In the first argument of `runQ', namely `(bez 2)' 
    In the expression: runQ (bez 2) 
    In an equation for `it': it = runQ (bez 2) 
*Main Language.Haskell.TH> runQ (boz 2) 
LamE [VarP y_0] (InfixE (Just (LitE (IntegerL 2))) (VarE GHC.Num.+) (Just (VarE y_0))) 
*Main Language.Haskell.TH> runQ (byz 2) 
AppE (VarE Main.g) (LitE (IntegerL 2)) 

मैं यहाँ क्या किया है runQ उपयोग करने के लिए वें जोड़ च कैसा दिखता है करने का प्रयास किया है या नमूना कोड में मेरे प्रत्येक कार्य। यह baz और bez पर विफल रहता है, लेकिन boz और byz के लिए काम करता है।

boz और byz के लिए वें को देखते हुए, हम देख सकते हैं कि कार्यों को उठा लिया जाता है: boz मूल रूप से सिर्फ नाम से + की चर्चा करते हुए किया जाता है (VarE GHC.Num.+ में) है, जबकि byz सिर्फ नाम से g की चर्चा करते हुए किया जाता है (VarE Main.g में)।

baz और bez के लिए, यह विकल्प तालिका पर नहीं है: दोनों कार्य f को विभाजित करने का प्रयास कर रहे हैं, जो स्थानीय रूप से बाध्य है; इसलिए, VarE f का संदर्भ baz और bez के बाहर समझ में नहीं आता है।

तो डेवलपर क्या करना है? संक्षेप में, [| f |] को आजमाने की बजाय, आपको लिफ्ट में सीधे f के लिए अभिव्यक्ति लिखनी होगी, पहचानकर्ताओं के संदर्भ में जो विभाजन होगा जहां विभाजन होगा।

एक तरफ ध्यान दें, बीजगणितीय डेटा प्रकारों के लिए Lift उदाहरण लिखना बहुत आसान है, क्योंकि आप हमेशा विश्व स्तर पर परिभाषित कार्यों को उठा सकते हैं।

instance Lift a => Lift (Maybe a) where 
    lift Nothing = [| Nothing |] 
    lift (Just a) = [| Just a |] 
+0

धन्यवाद! मैं TH की इस नई समझ के साथ चीजों को बदलकर चीजों को काम करने में सक्षम था। –

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