2012-02-29 17 views
6

निष्पादित मैं अपने आप को जैसेप्रिंट और एक स्ट्रिंग

 
putStr "foo (bar 1) (bar 2) =" 
print $ foo (bar 1) (bar 2) 

मुसीबत है, मुद्रित संदेश वास्तविक निष्पादित कोड के साथ सिंक से बाहर निकल सकते कोड का एक बहुत कुछ लिख पाते हैं। स्पष्ट समाधान इस कोड को स्वतः उत्पन्न करना है।

ऐसा करने का एक तरीका फ़ाइल में सभी टेक्स्ट डालना होगा, और एक छोटा प्रोग्राम लिखना होगा जो फ़ाइल को पढ़ता है और इससे हास्केल स्रोत कोड उत्पन्न करता है। लेकिन एक और विकल्प टेम्पलेट हास्केल का उपयोग करना है।

क्या कोई जानता है कि मैं String पर एक फ़ंक्शन लिखने के बारे में कैसे जाऊंगा और उपर्युक्त कोड उत्पन्न करता हूं? मुझे लगता है कि यह बहुत आसान होना चाहिए, लेकिन TH अच्छी तरह से प्रलेखित नहीं है।

+3

मैं सीपीपी का उपयोग करेंगे। कच्चे लेकिन इन प्रकार की चीजों के लिए प्रभावी। – augustss

+0

सीपीपी काम करता है - जब तक आप जिस पाठ को उद्धृत करना चाहते हैं, वह एक से अधिक पंक्ति तक फैलता है ... – MathematicalOrchid

+3

"मुझे लगता है कि मैं खुद को बहुत सारे कोड लिख रहा हूं [...] क्यों? –

उत्तर

8

आप haskell-src-meta पैकेज का उपयोग हास्केल कोड पार्स कर सकते हैं। यहां एक त्वरित उदाहरण दिया गया है कि आप इसे टेम्पलेट हास्केल के साथ कैसे जोड़ सकते हैं।

{-# LANGUAGE TemplateHaskell #-} 

import Language.Haskell.TH 
import Language.Haskell.TH.Quote 
import Language.Haskell.Meta 

runShow = QuasiQuoter 
    { quoteExp = runShowQQ 
    , quotePat = undefined 
    , quoteType = undefined 
    , quoteDec = undefined 
    } 

runShowQQ :: String -> Q Exp 
runShowQQ s = do 
    let s'   = s ++ " = " 
     Right exp = parseExp s 
     printExp = appE [|print|] (return exp) 
    infixApp [|putStr s'|] [|(>>)|] printExp 

और आप इस

{-# LANGUAGE QuasiQuotes #-} 

[runShow|foo (bar 1) (bar 2)|] 
+3

तो आप जो कह रहे हैं, किसी ने एक हास्केल पार्सर को अर्ध-उद्धरण के रूप में कार्यान्वित किया है, और आप इसका उपयोग कर सकते हैं? (यह प्यार करना चाहिए कि यह कैसे "अभी तक पूरा नहीं हुआ" है ...) ऐसा लगता है कि जीएचसी के _existing_ हास्केल पार्सर को पहली जगह अर्ध-उद्धरण के रूप में नहीं मानने में दयालुता है ... मुझे आश्चर्य है कि वे क्यों नहीं करते इसका समर्थन नहीं है? – MathematicalOrchid

+0

यह स्पष्ट रूप से सबसे अच्छा है जो TH के साथ किया जा सकता है, इसलिए मैं इस उत्तर को स्वीकार करने जा रहा हूं। – MathematicalOrchid

1

जीएचसी एपीआई here का उपयोग कर हास्केल कोड के समान eval का उदाहरण है।

4

टेम्पलेट हास्केल मनमाने ढंग से तारों को पार्स करने का सीधा साधन प्रदान नहीं करता है, इसलिए सबसे सरल समाधान संभवतः सी प्रीप्रोसेसर का उपयोग करना है। हालांकि, जीएचसी में अंतर्निहित एक स्ट्रिंगफिकेशन का समर्थन नहीं करता है, इसलिए हमें इसके बजाय "वास्तविक" का उपयोग करने के लिए अतिरिक्त विकल्प पारित करने की आवश्यकता है।

{-# LANGUAGE CPP #-} 
{-# OPTIONS_GHC -pgmP cpp #-} 

#define PRINT_EXP(x) (putStr #x >> putStr " = " >> print (x)) 

फिर आप इसे इस तरह उपयोग कर सकते हैं:

PRINT_EXP(foo (bar 1) (bar 2)) 
+0

मुझे उम्मीद थी कि टी स्ट्रिंग से पार्सिंग का समर्थन करे, लेकिन जैसा कि आप कहते हैं, ऐसा नहीं है। सबसे अप्रत्याशित मुझे लगता है कि आप "वास्तविक" सीपीपी का उपयोग करने के लिए देखते हैं; आप महसूस करते हैं कि विंडोज़ पर _isn't_ नहीं है, है ना? – MathematicalOrchid

0

आउच है जैसे कि यह प्रयोग करेंगे। I सोचा यह आसान होगा, लेकिन जहां तक ​​मैं कह सकता हूं, यह वास्तव में असंभव है।

मैं वहाँ उम्मीद कर रहा था एक समारोह है कि एक अभिव्यक्ति में एक स्ट्रिंग बदल जाता है हो सकता है, लेकिन जाहिरा तौर पर ऐसी कोई समारोह मौजूद है। डिस्क से अधिक स्रोत कोड लोड करने के लिए एक समारोह भी नहीं है। तो ऐसा लगता है कि यह काम वास्तव में असंभव है! मैं उस पर काफी हैरान हूँ।

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

आप इस प्रकार का सुविधा बहुत लागू करने के लिए तुच्छ हो जाएगा सोचा होगा। तथ्य यह है कि यह लागू नहीं है इसलिए केवल दो चीजों में से एक के लिए जिम्मेदार ठहराया जा सकता है:

  1. कोई भी वास्तव में इस सुविधा की जरूरत है। (ठीक है, मुझे छोड़कर, स्पष्ट रूप से।)

  2. यह रूप में तुच्छ के रूप में यह लग रहा है नहीं है। (जैसे, हो सकता है पता लगाना किस संदर्भ अभिव्यक्ति पार्स करने के लिए किसी भी तरह बारीकियों है में?)

+1

"यह वास्तव में असंभव है" - गलत। "ऐसा कोई कार्य मौजूद नहीं है [जो एक स्ट्रिंग को अभिव्यक्ति में बदल देता है]" - गलत। शांग का जवाब इन दोनों को लागू करता है। उसका TH उद्धृत स्ट्रिंग * बिल्कुल * आउटपुट करता है क्योंकि यह इनपुट था। असल में उन्होंने उस सटीक * चीज को लागू किया जिसके लिए आपने पूछा था, ठीक उसी कोड का उत्पादन। यह केवल शुद्ध, शोषक अभिव्यक्तियों के लिए काम करता है, और उन्हें 'आईओ()' में बदल देता है, लेकिन इसे आसानी से संशोधित किया जा सकता है: http://hpaste.org/64551 –

+1

यह केवल हास्केल अभिव्यक्तियों के लिए काम करता है जो तृतीय पक्ष हास्केल पार्सर जीएचसी पार्स कर सकते हैं कि किसी भी अभिव्यक्ति के लिए काम करता है। – MathematicalOrchid

0

तुम भी dump पैकेज है जो इस सटीक यूज-केस को संभालने के लिए लिखा गया था का उपयोग कर सकते हैं:

{-# language QuasiQuotes #-} 
import Debug.Dump 

main = putStrLn [d| foo (bar 1) (bar 2) |] 

foo = (+) 
bar = (+1) 

कौन सा प्रिंट: (foo (bar 1) (bar 2)) = 5

यह भी एक से अधिक अभिव्यक्ति द्वारा अलग संभालती है कॉमा:

putStrLn [d| foo (bar 1) (bar 2), map bar [1, 2] |] 

कौन सा प्रिंट: (foo (bar 1) (bar 2)) = 5 (map bar [1, 2]) = [2,3]

बोनस: आप (nix package manager का हिस्सा) nix-खोल स्थापित है, तो आप भी इसे बाहर जल्दी से इस "एक लाइनर" के साथ की कोशिश कर सकते हैं:

$ nix-shell -p "nix-shell -p "haskellPackages.ghcWithPackages (p: [p.dump])" --run "echo '{-# language QuasiQuotes #-}; import Debug.Dump; foo = (+); bar = (+1); main = putStrLn [d| foo (bar 1) (bar 2), map bar [1, 2] |]' | runhaskell"

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