custom-interpolation

Hackage Build Status License Hackage-Deps

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 `@{}`: ```hs i = interpolateQQ simpleConfig { handlers = [ simpleInterpolator {prefix = ""} , (applyInterpolator [|show . take 10|]) {prefix = "@"} ] } ``` ```hs >>> [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`](https://hackage.haskell.org/package/custom-interpolation/docs/CustomInterpolation.html#t: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. ```hs 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, [|"?"|])) }] } ``` ```hs >>> [sql|SELECT * FROM user WHERE id = {(11 ^ 5)} AND lastName = {"Smith"}|] ("SELECT * FROM user WHERE id = ? AND lastName = ?",[161051,"Smith"]) ``` ## Acknowledgements The [`CustomInterpolation.Parser`](https://github.com/ruby0b/custom-interpolation/blob/main/src/CustomInterpolation/Parser.hs) module was derived from the [`here` package](https://github.com/tmhedberg/here).