Provide basic QuasiQuoters in template-haskell?
Is there a reason why template-haskell
doesn't provide QuasiQuoters corresponding to TH quotes [e| ... |]
, [d| ... |]
, etc.? A lot of packages provide QuasiQuoters that could be written as "[e| ... |]
+ extra stuff"; for example, a text interpolation library could be implemented as
-- the QuasiQuoter corresponding to [e| ... |]
eQQ :: QuasiQuoter
-- Interpolate: (let x = 1 in [text|x is: #{x}|]) == "x is: 1"
text :: QuasiQuoter
text =
eQQ
{ quoteExp =
appE [| concat |]
. listE
. map
( \case
Left raw -> litE $ stringL raw
Right interpolated -> quoteExp eQQ interpolated
)
. parse
}
-- Parses "x is: #{x}" into [Left "x is: ", Right "x"]
parse :: String -> [Either String String]
Whereas currently, it'd have to pull in haskell-src-meta
to parse the string.
As another example, we have a use case for easily writing lists of hlists:
rows =
eQQ
{ quoteExp = listE . map (toHList . quoteExp eQQ) . lines
}
-- generates [1 :& "hello" :& True :& Nil, 2 :& "world" :& False :& Nil]
[rows|
[1, "hello", True]
[2, "world", False]
|]
Today, the best way to do this without haskell-src-meta
is to do
rows = listE . map toHList
$( rows
[ [| [1, "hello", True] |]
, [| [2, "world", False] |]
]
)
I would imagine it's not straightforward, with the parsing of the TH quotes probably builtin to the compiler and not available at runtime, but if it's just a matter of breaking out the logic, I think it would be a big win on writing common QuasiQuoters