2012-02-11 30 views
8

मैं एक साधारण HashString वर्ग, जो सिर्फ एक स्ट्रिंग और उसके हैश है लिख रहा हूँ के साथ संकलन समय पर एक समारोह का मूल्यांकन:खाका हास्केल

data HashString = HashString Int --^hash 
          T.Text --^string! 

अब मैं की तरह कुछ के साथ संकलन समय पर इन उत्पन्न करने के लिए कोशिश कर रहा हूँ :

$(hString "hello, world") :: HashString 

मैं हैश चाहता हूं, और टेक्स्ट पैकिंग संकलन समय पर होने वाला है। मैं यह कैसे करु?

यहाँ मैं अब तक की कोशिश की है, लेकिन मैं अगर यह सही यकीन नहीं है, और न ही मुझे यकीन है कि यह संकलन समय पर सब कुछ करता है हूँ:

hString :: String -> Q Exp 
hString s = [| HashString (hash $ T.pack s) (T.pack s) |] 

उत्तर

14

तरह से आप अपने कोड लिखा है, संकलन समय पर कोई मूल्यांकन नहीं होगा। जब आप [| ... |] के साथ एक हास्केल अभिव्यक्ति बोली, उद्धृत कोड/एएसटी डाला जाता है जहां आप इसे किसी भी मूल्यांकन के बिना लागू होते हैं, तो लेखन:

$(hString "hello, world") 

लेखन के रूप में बिल्कुल वैसा ही है:

let s = "hello, world" in HashString (hash $ T.pack s) (T.pack s) 

लेकिन लगता है इसके बारे में: आप [| ... |] का उपयोग बाद में सम्मिलित होने वाली अभिव्यक्ति को उद्धृत करने के लिए करते हैं, और आप $(...) के साथ संकलन-समय पर कोड उत्पन्न करते हैं। इसलिए, यदि आप उद्धृत अभिव्यक्ति bla = [| bar $(foo) |] में कुछ कोड $(foo) शामिल करते हैं, तो $(bla) कोड bar $(foo) उत्पन्न करेगा, जो बदले में foo संकलन समय पर मूल्यांकन करेगा। साथ ही, संकलन समय पर उत्पन्न होने वाले मान को लेने और उससे अभिव्यक्ति उत्पन्न करने के लिए, आप lift फ़ंक्शन का उपयोग करते हैं। तो, क्या आप क्या करना चाहते है:

import Data.String (fromString) 
import Language.Haskell.TH.Syntax 

hString s = [| HashString $(lift . hash . T.pack $ s) (fromString s) |] 

यह संकलन समय पर हैश फंक्शन का मूल्यांकन करता है, के बाद से आंतरिक जोड़ के बाद बाहरी जोड़ हल किया गया था हल हो गई है। वैसे, Data.String से fromString का उपयोग से कुछ OverloadedString डेटा प्रकार बनाने का सामान्य तरीका है।

इसके अलावा, आपको अपने HashString इंटरफ़ेस के लिए अर्ध-उद्धरण बनाने पर विचार करना चाहिए। अर्ध-उद्धरण का उपयोग मैन्युअल रूप से स्प्लिस फ़ंक्शंस को कॉल करने से अधिक प्राकृतिक है (और आप पहले ही उनका उपयोग कर चुके हैं; नामहीन [| ... |] उद्धरण उद्धरण हास्केल अभिव्यक्तियां)।

आप इस प्रकार का quasiquoter बनाना होगा:

import Language.Haskell.TH.Quote 

hstr = 
    QuasiQuoter 
    { quoteExp = hString -- Convenient: You already have this function 
    , quotePat = undefined 
    , quoteType = undefined 
    , quoteDec = undefined 
    } 

यह जाने हैं तो आप इस वाक्य रचना के साथ HashString रों लिखें:

{-# LANGUAGE QuasiQuotes #-} 
myHashString = [hstr|hello, world|] 
+0

बहुत बढ़िया जवाब! धन्यवाद। –

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