custom-interpolation: Customizable string interpolation quasiquoters

[ bsd3, interpolation, library, quasiquotes, text ] [ Propose Tags ] [ Report a vulnerability ]

Flags

Manual Flags

NameDescriptionDefault
doctests

Run doctests using doctests-parallel, disabled by default due to https://github.com/martijnbastiaan/doctest-parallel/issues/22

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.1.0.0, 0.1.0.1
Change log changelog.md
Dependencies base (>=4.14 && <5), data-default-class (>=0.1 && <0.2), haskell-src-meta (>=0.6 && <0.9), mtl (>=2.1 && <2.4), parsec (>=3.1 && <3.2), template-haskell (>=2.16 && <2.20) [details]
Tested with ghc ==8.10.7 || ==9.2.5 || ==9.4.4
License BSD-3-Clause
Author ruby0b
Maintainer ruby0b
Category Interpolation, QuasiQuotes, Text
Home page https://github.com/ruby0b/custom-interpolation
Source repo head: git clone git://github.com/ruby0b/custom-interpolation.git
Uploaded by ruby0b at 2023-01-12T02:58:52Z
Distributions
Reverse Dependencies 1 direct, 0 indirect [details]
Downloads 147 total (9 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for custom-interpolation-0.1.0.1

[back to package description]

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 @{}:
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.