我想创建一个表达式,以便我有一个编译时错误或URI。
[uri|http://stackoverflow.com|]
应编译,但
[uri|foo:/bar:\|]
不应该。
我遇到过QuasiQuotes,显然是出于这种问题。但是,我似乎无法从解析后的Q Exp
创建URI
。
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 |]
}
无法编译,因为它需要Lift
的{{1}}实例。但是,由于GADT的性质,我不确定如何创建一个。
URI
抱怨没有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)
,但我不确定如何将它们与QQ API一起使用。
答案 0 :(得分: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
的情况下,您可以为所有类型创建孤立Lift
个实例{{1依赖(传递)on。
URIRef
通过此添加,您的代码现在可以编译。在GHCi,我得到以下互动,确认一切正常。
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
刚刚注意到我从未回答你问题的最后部分。
我更喜欢使用Generics,但我不确定如何将它们与QQ API一起使用。
这是不可能的 - 通用编程不允许您在编译时执行任意验证代码。你真的需要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
代码中使用它们,但这是不必要的(那里没有通用的东西)。