{"id":26345542,"url":"https://github.com/ruby0b/custom-interpolation","last_synced_at":"2025-08-09T00:04:37.301Z","repository":{"id":65211849,"uuid":"587971682","full_name":"ruby0b/custom-interpolation","owner":"ruby0b","description":"Customizable string interpolation quasiquoters","archived":false,"fork":false,"pushed_at":"2023-01-13T15:15:09.000Z","size":13,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-26T12:57:47.185Z","etag":null,"topics":["haskell","string-interpolation"],"latest_commit_sha":null,"homepage":"https://hackage.haskell.org/package/custom-interpolation","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruby0b.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2023-01-12T02:30:59.000Z","updated_at":"2024-12-23T03:59:14.000Z","dependencies_parsed_at":"2023-01-15T15:15:44.806Z","dependency_job_id":null,"html_url":"https://github.com/ruby0b/custom-interpolation","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ruby0b/custom-interpolation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0b%2Fcustom-interpolation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0b%2Fcustom-interpolation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0b%2Fcustom-interpolation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0b%2Fcustom-interpolation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruby0b","download_url":"https://codeload.github.com/ruby0b/custom-interpolation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0b%2Fcustom-interpolation/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269508465,"owners_count":24428733,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-08T02:00:09.200Z","response_time":72,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["haskell","string-interpolation"],"created_at":"2025-03-16T06:18:56.774Z","updated_at":"2025-08-09T00:04:37.211Z","avatar_url":"https://github.com/ruby0b.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ecustom-interpolation\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://hackage.haskell.org/package/custom-interpolation\"\u003e\u003cimg src=\"https://img.shields.io/hackage/v/custom-interpolation\" alt=\"Hackage\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/ruby0b/custom-interpolation/actions/workflows/haskell-ci.yml\"\u003e\u003cimg src=\"https://github.com/ruby0b/custom-interpolation/actions/workflows/haskell-ci.yml/badge.svg\" alt=\"Build Status\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/simmsb/calamity/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/ruby0b/custom-interpolation\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://hackage.haskell.org/package/custom-interpolation\"\u003e\u003cimg src=\"https://img.shields.io/hackage-deps/v/custom-interpolation\" alt=\"Hackage-Deps\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nThis library provides tools for easily generating string interpolation quasiquoters.\nThe interpolation behavior is customizable and multiple different interpolation methods may be used in a single quasiquoter.\n\n## Usage Examples\n\n### Example 1: Multiple interpolators\n\nLet's define a basic string interpolation quasiquoter that\n\n- interpolates any Haskell expressions using `{}` and\n- shows the first 10 elements of a list using `@{}`:\n\n```hs\ni = interpolateQQ simpleConfig\n  { handlers = [ simpleInterpolator {prefix = \"\"}\n               , (applyInterpolator [|show . take 10|]) {prefix = \"@\"} ] }\n```\n\n```hs\n\u003e\u003e\u003e [i|2^10 = {show (2 ^ 10)}. Some Fibonacci numbers: @{let fibs = 1 : 1 : zipWith (+) fibs (tail fibs) in fibs}.|]\n\"2^10 = 1024. Some Fibonacci numbers: [1,1,2,3,5,8,13,21,34,55].\"\n```\n\n### Example 2: SQL substitution\n\nNow for a more complicated example; defining an SQL query quasiquoter that prevents SQL injection.\n\nWe 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.\nThis allows us to then apply some SQL library function to the string and the accumulated expressions which takes care of the actual substitution.\n\n```hs\nimport Language.Haskell.TH (appE, listE, Exp, Q)\n\n-- Need an existential type to wrap the differently typed interpolated expressions\ndata SQLData = forall a. Show a =\u003e SQLData a\ninstance Show SQLData where show (SQLData x) = show x\n\n-- Dummy function that would normally run the query\nrunSQL sql ds = (sql, ds)\n\n-- The quasiquoter itself\nconsumeInterpolated :: ([Q Exp], Q Exp) -\u003e Q Exp\nconsumeInterpolated (exprs, strExpr) = appE (appE [|runSQL|] strExpr) (listE (map (appE [|SQLData|]) exprs))\n\nsql = interpolateQQ defaultConfig\n    { finalize = consumeInterpolated,\n      handlers = [simpleInterpolator { handler = (\\q -\u003e (q, [|\"?\"|])) }]\n    }\n```\n\n```hs\n\u003e\u003e\u003e [sql|SELECT * FROM user WHERE id = {(11 ^ 5)} AND lastName = {\"Smith\"}|]\n(\"SELECT * FROM user WHERE id = ? AND lastName = ?\",[161051,\"Smith\"])\n```\n\n## Acknowledgements\n\nThe [`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).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruby0b%2Fcustom-interpolation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruby0b%2Fcustom-interpolation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruby0b%2Fcustom-interpolation/lists"}