{"id":16312305,"url":"https://github.com/namin/minikanren-confo","last_synced_at":"2025-08-31T14:38:12.685Z","repository":{"id":7546710,"uuid":"8899398","full_name":"namin/minikanren-confo","owner":"namin","description":"core.logic.nominal at the minikanren confo 2013","archived":false,"fork":false,"pushed_at":"2023-02-09T00:51:55.000Z","size":31,"stargazers_count":18,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-23T09:09:41.142Z","etag":null,"topics":["binders","clojure","minikanren","paper-implementations"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/namin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-03-20T08:29:03.000Z","updated_at":"2025-05-07T20:23:59.000Z","dependencies_parsed_at":"2024-10-28T14:50:58.389Z","dependency_job_id":null,"html_url":"https://github.com/namin/minikanren-confo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/namin/minikanren-confo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/namin%2Fminikanren-confo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/namin%2Fminikanren-confo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/namin%2Fminikanren-confo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/namin%2Fminikanren-confo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/namin","download_url":"https://codeload.github.com/namin/minikanren-confo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/namin%2Fminikanren-confo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272993072,"owners_count":25027702,"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-31T02:00:09.071Z","response_time":79,"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":["binders","clojure","minikanren","paper-implementations"],"created_at":"2024-10-10T21:47:41.166Z","updated_at":"2025-08-31T14:38:12.649Z","avatar_url":"https://github.com/namin.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [`core.logic.nominal`](https://github.com/clojure/core.logic/blob/master/src/main/clojure/clojure/core/logic/nominal.clj) talk\n\n## Run the examples from the [talk](src/talk.clj)\n\n`lein test talk`\n\n## `core.logic.nominal`\n\n`core.logic.nominal` extends `core.logic` to simplify writing type\ninferencers, interpreters and other such programs that must reason about\nscope and binding. Compared to other approaches for reasoning about\nscope and binding, the nominal technique really captures the conventions\nused on paper. Furthermore, nominal logic fully integrates with logic\nprogramming, which means that that it just works in the presence of\nunbound logic variables.\n\n## Why?\n\nI implemented `core.logic.nominal` to integrate (1) relational, (2)\nconstraint-based and (3) nominal techniques in one tool. Each of these\ntechniques is independently useful for exploring semantics of\nprogramming languages and type systems. (1) If you implement your type\nsystem as a relational program, you get not only a type checker, but\nalso a generator of well-typed terms, and possibly a type\ninferencer. (2) If you express the rules of your type system as\nconstraints, and are able to monitor those constraints, then you can\npossibly turn your type checker into a type debugger. (3) Nominal\nabstract syntax simplifies reasoning about names and bindings so that you\ncan use the same conventions in your implementation as on paper.\n\n\n## Nominal Logic Programming\n\nNominal logic programming brings nominal abstract syntax to logic\nprogramming. Nominal abstract syntax is a technique for reasoning about\nscope and binding, which is fairly close to what is done \"on paper\".  On\npaper, one uses explicit names for bound variables, while assuming the\nchoice of name is unimportant, as long as the binding structure is\npreserved.\n\nNominal abstract syntax formalizes this paper intuition, making it\neasier to write programs, such as type inferencers and interpreters,\nthat must reason about scope and binding. Furthermore, nominal logic\nprogramming maintains the intuitive reasoning about scope and binding of\nnominal abstract syntax, even in the presence of unbound logic\nvariables.\n\n## Reasoning about scope\n\nConsider the lambda calculus, `e := x | (e e) | λx.e`.\n\nA λ-term is a _binder_ because it _binds_ a name `x` in the term\n`e`. Intuitively, the choice of the _bound_ names are unimportant, as\nlong as the same binding structure is represented, e.g.  `λa.a ≡α λb.b`\nand `λa.λb.a ≡α λb.λa.b` but `λa.λb.a ≢α λb.λa.a`.\n\nThis intuitive notion of equality for binders is known as\nα-equivalence. Formally, `λa.e ≡α λb.[b/a]e` where `b` does not occur\nfree in `e`.\n\nThe side-condition in the definition of α-equivalence is a _freshness\nconstraint_. Indeed, `λa.a ≢α λb.a` because `a` is bound in `λa.a` and\n_free_ in `λb.a`.\n\nThese two useful notions, α-equivalence and freshness constraints, are\nbuilt into nominal logic programming. They enable programmers to reason\nabout scope and binding, even in the presence of unbound logic\nvariables, common in logic programs.\n\n## Example: capture-avoiding substitution\n\n## The three constructs of `core.logic.nominal`\n\ncore.logic.nominal extends core.logic with three constructs for nominal\nlogic programming: `fresh`, `tie`, and `hash`.\n\n### `nom/fresh`\n\nThe operator `nom/fresh` introduces new names, just like `fresh` introduces\nnew variables.\n\nA \"nom\" only unifies with itself or with an unbound variable.\n\nA reified nom consists of the symbol `a` subscripted by a number: `a_0`, `a_1`, etc.\n\n### `nom/tie`\n\nThe term constructor `nom/tie` binds a nom in a term. Binders are\nunified up to alpha-equivalence.\n\n### `nom/hash`\n\nThe operator `nom/hash` introduces a _freshness constraint_, asserting\nthat a nom does not occur _free_ in a term.\n\n## Example: type inferencer\n\n## Run your research!\n\n### Example: type debugger\n\n[PDF](http://lampwww.epfl.ch/~amin/nominal/type_deriv_exs.pdf) of auto-generated derivation and debug trees\n\n\n### Example: generator of counterexamples to meta-theoretic properties\n\n## Under the hood: swapping!\n\nNominal unification is specified using nom-swaps and `#`-constraints.\n\nTwo binders `t1` and `t2` unify when either:\n\n* `t1` is `[a] c1`, `t2` is `[a] c2` and `c1` unifies with `c2`, or\n* `t1` is `[a] c1`, `t2` is `[b] c2`, `a#c2`, and `c1` unifies with the\n  term `c2` with all `a`s and `b`s swapped.\n\nSwapping introduces suspensions, because when we encounter a variable\nduring swapping, we must delay the swap until the variable is bound.\n\nIn core.logic.nominal, we implement suspensions as constraints. During\nswapping of `a` and `b`, whenever we encounter a variable `x`, we\nreplace it with a fresh variable `x'` and add the suspension constraint\nswap `[a b] x' x`. This swap constraint is executed under one of two\nconditions:\n\n* `x` and `x'` both become bound -- the swapping can resume\n* `x` and `x'` become equal -- we enforce `a#x'` and `b#x'` and drop the\n  swap constraint\n\n## Some References\n\n- _alphaKanren_ ([PDF](http://webyrd.net/alphamk/alphamk.pdf))\n- _Nominal Unification_ ([PDF](https://www.cl.cam.ac.uk/~amp12/papers/nomu/nomu.pdf]))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnamin%2Fminikanren-confo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnamin%2Fminikanren-confo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnamin%2Fminikanren-confo/lists"}