2013-05-02 4 views
6

मैं एक मॉड्यूल में निम्न कोड:खाका हास्केल: GHC चरण प्रतिबंध और कैसे काबू पाने के लिए

{-# LANGUAGE TemplateHaskell #-} 

module Alpha where 

import Language.Haskell.TH 
import Data.List 

data Alpha = Alpha { name :: String, value :: Int } deriving (Show) 
findName n = find ((== n) . name) 

findx obj = sequence [valD pat bod []] 
    where 
     nam = name obj 
     pat = varP (mkName $ "find" ++ nam) 
     bod = normalB [| findName nam |] 

और फिर मैं मुख्य फ़ाइल में निम्न है:

{-# LANGUAGE TemplateHaskell #-} 

import Alpha 

one = Alpha "One" 1 
two = Alpha "Two" 2 
three = Alpha "Three" 3 
xs = [one, two , three] 

findOne = findName "One" 
findTwo = findName "Two" 

$(findx three) -- This Fails 
$(findx (Alpha "Four" 4)) -- This Works 

main = putStrLn "Done" 

मैं था मेरे लिए findThree = findName "Three" बनाने के लिए $(findx three) की तरह। लेकिन इसके बजाय, मुझे यह त्रुटि मिलती है:

GHC stage restriction: `three' 
    is used in a top-level splice or annotation, 
    and must be imported, not defined locally 
In the first argument of `findx', namely `three' 
In the expression: findx three 

मैं इसे कैसे दूर करूं? मुझे एक अलग फ़ाइल में one, two, आदि को परिभाषित करने की आवश्यकता नहीं है।

दूसरा प्रश्न यह है कि $(findx (Alpha "Four" 4)) समस्या के बिना काम क्यों करता है?

+1

यदि आप उसी मॉड्यूल में किसी नाम को संदर्भित करने का प्रयास कर रहे हैं, तो आप इसे किसी भी तरह उद्धरण/अर्ध-उद्धरण के साथ करने में सक्षम हो सकते हैं? यदि आप एक splice में वास्तव में _execute_ करने की कोशिश कर रहे हैं, तो इसे भूल जाओ। संकलक मूल रूप से ऐसा नहीं कर सकता है। – MathematicalOrchid

+1

ठीक है। '$ (Findx तीन)' और '$ (findx (अल्फा" चार "4) के बीच अंतर क्या है? पूर्व में वास्तव में त्रुटि में परिणाम होता है लेकिन बाद वाला काम करता है। – me2

+1

'तीन' उसी मॉड्यूल में परिभाषित किया गया है, जबकि 'अल्फा' नहीं है। – yiding

उत्तर

6

मैं बहुत खाका हास्केल अपने आप भर में मेरी सीमित समस्या को समझने कि three कुछ अर्थों में है कि "अभी भी परिभाषित किया जा रहा" के आधार पर नहीं कर रहा हूँ, लेकिन जब GHC $(findx three) संकलित करने के लिए, जबकि सभी $(findx (Alpha "Four" 4)) के घटक टुकड़े कर रहे हैं कोशिश कर रहा है पहले ही पूरी तरह परिभाषित है।

मौलिक मुद्दा यह है कि उसी मॉड्यूल में सभी परिभाषा एक दूसरे के के अर्थ को प्रभावित करती है। यह प्रकार अनुमान के साथ ही पारस्परिक रिकर्सन के कारण है। संदर्भ के आधार पर परिभाषा x = [] का अर्थ कई अलग-अलग चीजों का हो सकता है; यह xInt की सूची में IO(), या कुछ और की सूची में बाध्यकारी हो सकता है। जीएचसी को पूरे मॉड्यूल को संसाधित करना पड़ सकता है कि यह पता लगाने के लिए कि का मतलब है (या यह वास्तव में एक त्रुटि है)।

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

अन्य मॉड्यूल ओटीओएच से आयात की गई चीजें पहले ही पूरी तरह से जांच की गई हैं जब जीएचसी ने संकलित किया है मॉड्यूल। इस मॉड्यूल को संकलित करके उनके बारे में और जानकारी नहीं है। इसलिए इन मॉड्यूल में कोड के संकलन से पहले उन तक पहुंचा जा सकता है और इस्तेमाल किया जा सकता है।

इसके बारे में सोचने का एक और तरीका: शायद three वास्तव में Alpha प्रकार का नहीं होना चाहिए। शायद वह एक टाइपो था और कन्स्ट्रक्टर Alphz होना चाहिए था। आम तौर पर जीएचसी मॉड्यूल में अन्य सभी कोड संकलित करके त्रुटियों के उन प्रकारों के बारे में पता लगाता है जो three का उपयोग यह देखने के लिए करते हैं कि क्या यह असंगतता है या नहीं। लेकिन क्या होगा अगर कोड उन चीज़ों द्वारा उपयोग या उपयोग किया जाता है जो केवल $(findx three) द्वारा उत्सर्जित होते हैं? हम यह भी नहीं जानते कि जब तक हम इसे चलाएंगे तब तक कौन सा कोड होने वाला है, लेकिन हम इस सवाल को व्यवस्थित नहीं कर सकते कि three इसे चलाने के बाद ठीक से टाइप किया गया है या नहीं।

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

+0

मुझे लगता है कि आप टेम्पलेट हास्केल को जो भी पारित कर सकते हैं उस पर प्रतिबंध वास्तव में अधिक जटिल नहीं होंगे, लेकिन कोडिंग करना बहुत मुश्किल हो सकता है। –

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