You're almost there - the Lift Bytestring
instance you're looking for is featured in the th-lift-instances
package.
import Instances.TH.Lift
Of course, you can also just copy the corresponding instance instead of imposing a dependency.
-- ByteString instance Lift ByteString where lift b = [| pack $(lift $ unpack b) |]
Then, when you enable DeriveLift
, StandaloneDeriving
, GADTs
and TemplateHaskell
you can instantiate Lift
orphans for all URIRef
types that are (transitive) dependent.
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
With this add-on, your code is now compiled. In GHCi, I get the following interaction, confirming that everything works.
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>
EDIT
Just noticed that I never answered the last part of your question.
I would prefer to use Generics, but I'm not sure how to use them with the QQ API.
It will be impossible. General programming will not allow you to execute arbitrary verification code at compile time. For this you really need TemplateHaskell
. At best, you can use them inside the generated TemplateHaskell
code, but that would be optional (there is nothing to do with it).