@hackage custom-interpolation0.1.0.1
Customizable string interpolation quasiquoters
Categories
License
BSD-3-Clause
Maintainer
ruby0b
Links
Versions
Installation
Tested Compilers
Dependencies (6)
- base >=4.14 && <5
- data-default-class ^>=0.1
- haskell-src-meta >=0.6 && <0.9
- mtl >=2.1 && <2.4
- parsec ^>=3.1
- template-haskell >=2.16 && <2.20 Show all…
Dependents (1)
@hackage/sqlite-simple-interpolate
Package Flags
doctests
(off by default)
Run doctests using doctests-parallel, disabled by default due to https://github.com/martijnbastiaan/doctest-parallel/issues/22
custom-interpolation
This library provides tools for easily generating string interpolation quasiquoters. The interpolation behavior is customizable and multiple different interpolation methods may be used in a single quasiquoter.
Usage Examples
Example 1: Multiple interpolators
Let's define a basic string interpolation quasiquoter that
- interpolates any Haskell expressions using
{}and - shows the first 10 elements of a list using
@{}:
i = interpolateQQ simpleConfig
{ handlers = [ simpleInterpolator {prefix = ""}
, (applyInterpolator [|show . take 10|]) {prefix = "@"} ] }
>>> [i|2^10 = {show (2 ^ 10)}. Some Fibonacci numbers: @{let x = (\fibs -> 1 : 1 : zipWith (+) fibs (tail fibs)) x in x}.|]
"2^10 = 1024. Some Fibonacci numbers: [1,1,2,3,5,8,13,21,34,55]."
Example 2: SQL substitution
Now for a more complicated example; defining an SQL query quasiquoter that prevents SQL injection.
We can achieve this by replacing expressions between {} with ? and accumulating the actual expression in the first output of the Interpolator handler.
This allows us to then apply some SQL library function to the string and the accumulated expressions which takes care of the actual substitution.
import Language.Haskell.TH (appE, listE, Exp, Q)
-- Need an existential type to wrap the differently typed interpolated expressions
data SQLData = forall a. Show a => SQLData a
instance Show SQLData where show (SQLData x) = show x
-- Dummy function that would normally run the query
runSQL sql ds = (sql, ds)
-- The quasiquoter itself
consumeInterpolated :: ([Q Exp], Q Exp) -> Q Exp
consumeInterpolated (exprs, strExpr) = appE (appE [|runSQL|] strExpr) (listE (map (appE [|SQLData|]) exprs))
sql = interpolateQQ defaultConfig
{ finalize = consumeInterpolated,
handlers = [simpleInterpolator { handler = (\q -> (q, [|"?"|])) }]
}
>>> [sql|SELECT * FROM user WHERE id = {(11 ^ 5)} AND lastName = {"Smith"}|]
("SELECT * FROM user WHERE id = ? AND lastName = ?",[161051,"Smith"])
Acknowledgements
The CustomInterpolation.Parser module was derived from the here package.