custom-interpolation: Customizable string interpolation quasiquoters

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

Please see the readme at https://github.com/ruby0b/custom-interpolation#readme.


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.1.0.1, 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]
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:09Z

Modules

[Index] [Quick Jump]

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


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

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.