2017-02-09 11 views
6

मैं एक अभिव्यक्ति बनाना चाहता हूं कि मेरे पास एक संकलन त्रुटि हो या URIसंकलित समय की जांच यूआरआई

[uri|http://stackoverflow.com|] 

संकलन करना चाहिए, लेकिन

[uri|foo:/bar:\|] 

नहीं करना चाहिए।

मैं QuasiQuotes में आया हूं, जो स्पष्ट रूप से इस तरह की समस्या के लिए हैं। हालांकि, मैं पार्स किए गए URI से Q Exp बनाने के लिए प्रतीत नहीं कर सकता।

import Language.Haskell.TH.Quote 
import Language.Haskell.TH.Syntax 
import Language.Haskell.TH 
import URI.ByteString 
import Data.ByteString.Char8 


uri = QuasiQuoter { quoteExp = \s -> 
         let 
         uri = either (\err -> error $ show err) id (parseURI laxURIParserOptions (pack s)) 
         in 
         [| uri |] 
        } 

संकलन नहीं करता है, क्योंकि यह URI के लिए एक Lift उदाहरण चाहता है। हालांकि, मुझे यकीन नहीं है कि जीएडीटी प्रकृति के कारण, एक कैसे बनाया जाए।

deriving instance Lift (URIRef a) 

कोई Lift ByteString के बारे में शिकायत करता है, लेकिन मैं विचार कोई भी लिखने के लिए की है। एक और तरीका है Data URI होगा, लेकिन है कि

85 1 error   • Couldn't match type ‘a’ with ‘Absolute’ 
    ‘a’ is a rigid type variable bound by 
    the instance declaration at uri-bytestring/src/URI/ByteString/Types.hs:85:1 
    Expected type: c (URIRef a) 
    Actual type: c (URIRef Absolute) 
• In the expression: k (k (k (k (k (z URI))))) 
    In a case alternative: 
     ghc-prim-0.5.0.0:GHC.Types.I# 1# -> k (k (k (k (k (z URI))))) 
    In the expression: 
    case constrIndex c of { 
     ghc-prim-0.5.0.0:GHC.Types.I# 1# -> k (k (k (k (k (z URI))))) 
     _ -> k (k (k (k (z RelativeRef)))) } 
    When typechecking the code for ‘gunfold’ 
    in a derived instance for ‘Data (URIRef a)’: 
    To see the code I am typechecking, use -ddump-deriv 
• Relevant bindings include 
    gunfold :: (forall b r. Data b => c (b -> r) -> c r) 
       -> (forall r. r -> c r) -> Constr -> c (URIRef a) 
     (bound at uri-bytestring/src/URI/ByteString/Types.hs:85:1) (haskell-stack-ghc) 

के साथ विफल रहा Generics उपयोग करने के लिए पसंद करते हैं, लेकिन मैं कैसे QQ API के साथ उन्हें इस्तेमाल करने के यकीन नहीं है।

उत्तर

10

आप लगभग वहां हैं - Lift Bytestring उदाहरण जो आप ढूंढ रहे हैं th-lift-instances पैकेज में प्रदान किया गया है।

import Instances.TH.Lift 

बेशक, आप केवल निर्भरता के बजाय प्रासंगिक उदाहरण की प्रतिलिपि बना सकते हैं।

-- ByteString 
instance Lift ByteString where 
    lift b = [| pack $(lift $ unpack b) |] 

फिर, साथ DeriveLift, StandaloneDeriving, GADTs, और TemplateHaskell चालू है, तो आप सभी प्रकार URIRef निर्भर करता है (संक्रामक) पर के लिए अनाथ Lift उदाहरण बना सकते हैं।

deriving instance Lift (URIRef a) 
deriving instance Lift Authority 
deriving instance Lift UserInfo 
deriving instance Lift Query 
deriving instance Lift Host 
deriving instance Lift Port 
deriving instance Lift Scheme 

इस अतिरिक्त के साथ, अब आपका कोड संकलित करता है। जीएचसीआई में मुझे निम्नलिखित बातचीत मिलती है, सबकुछ काम करता है।

ghci> :set -XQuasiQuotes 
ghci> [uri|http://stackoverflow.com|] 
URI {uriScheme = Scheme {schemeBS = "http"}, uriAuthority = Just (Authority {authorityUserInfo = Nothing, authorityHost = Host {hostBS = "stackoverflow.com"}, authorityPort = Nothing}), uriPath = "", uriQuery = Query {queryPairs = []}, uriFragment = Nothing} 
ghci> [uri|foo:/bar:\|] 

<interactive>:3:1: error: 
    • Exception when trying to run compile-time code: 
     MalformedPath 
CallStack (from HasCallStack): 
    error, called at uri.hs:25:47 in main:Main 
     Code: quoteExp uri "foo:/bar:\\" 
    • In the quasi-quotation: [uri|foo:/bar:\|] 
ghci> 

संपादित

बस देखा मैं अपने प्रश्न के अंतिम भाग कभी नहीं जवाब दे दिया।

मैं जेनिक्स का उपयोग करना पसंद करूंगा, लेकिन मुझे यकीन नहीं है कि क्यू क्यू एपीआई के साथ उनका उपयोग कैसे करें।

यह संभव नहीं होगा - सामान्य प्रोग्रामिंग आपको संकलन समय पर मनमाने ढंग से सत्यापन कोड निष्पादित करने नहीं देगा। इसके लिए आपको वास्तव में TemplateHaskell की आवश्यकता है। सबसे अच्छा आप उन्हें TemplateHaskell कोड के अंदर उपयोग कर सकते हैं, लेकिन यह अनावश्यक होगा (वहां करने के लिए सामान्य कुछ भी नहीं है)।

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