{"id":19489355,"url":"https://github.com/redprl/ocaml-bwd","last_synced_at":"2026-03-17T11:33:40.006Z","repository":{"id":42365788,"uuid":"475241925","full_name":"RedPRL/ocaml-bwd","owner":"RedPRL","description":"🔙 Backward lists for OCaml","archived":false,"fork":false,"pushed_at":"2024-09-29T00:13:55.000Z","size":664,"stargazers_count":22,"open_issues_count":4,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-25T18:41:12.952Z","etag":null,"topics":["ocaml","ocaml-library"],"latest_commit_sha":null,"homepage":"https://ocaml.org/p/bwd","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RedPRL.png","metadata":{"files":{"readme":"README.markdown","changelog":"CHANGELOG.markdown","contributing":"CONTRIBUTING.markdown","funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2022-03-29T01:48:26.000Z","updated_at":"2024-12-19T18:03:24.000Z","dependencies_parsed_at":"2025-04-25T18:49:01.804Z","dependency_job_id":null,"html_url":"https://github.com/RedPRL/ocaml-bwd","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/RedPRL/ocaml-bwd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RedPRL%2Focaml-bwd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RedPRL%2Focaml-bwd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RedPRL%2Focaml-bwd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RedPRL%2Focaml-bwd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RedPRL","download_url":"https://codeload.github.com/RedPRL/ocaml-bwd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RedPRL%2Focaml-bwd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30622749,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T11:26:08.186Z","status":"ssl_error","status_checked_at":"2026-03-17T11:24:37.311Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["ocaml","ocaml-library"],"created_at":"2024-11-10T21:08:18.196Z","updated_at":"2026-03-17T11:33:39.991Z","avatar_url":"https://github.com/RedPRL.png","language":"OCaml","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🔙 Backward Lists\n\nThis OCaml package defines backward lists that are isomorphic to lists.\nThey are useful when one wishes to give a different type to the lists that are semantically in reverse.\nIn our experience, it is easy to miss `List.rev` or misuse `List.rev_append` when both semantically forward and backward lists are present.\nWith backward lists having a different type, it is impossible to make those mistakes.\n\n## API Stability and Documentation\n\nThe API is relatively stable. [Here is the API documentation.](https://redprl.org/ocaml-bwd/bwd/Bwd/)\n\n## How to Use It\n\n### OCaml \u003e= 4.14\n\nYou need OCaml 4.14.0 or newer to enjoy the [experimental TMC feature](https://www.ocaml.org/manual/tail_mod_cons.html). Otherwise, there will be warnings about incorrect `tailcall` annotations because order versions of OCaml cannot automatically transform some functions into tail-recursive ones.\n\n### OPAM\n\nThe package is available in the OPAM repository:\n\n```sh\nopam install bwd\n```\n\nYou can also pin the latest version in development:\n\n```sh\nopam pin https://github.com/RedPRL/bwd.git\n```\n\n### Example Code\n\n```ocaml\nopen Bwd\nopen Bwd.Infix\n\n(* [Emp] is the empty list and [\u003c:] is snoc (cons in reverse).\n   The following expression gives the backward list corresponding to [1; 2; 3]. *)\nlet b1 : int bwd = Emp \u003c: 1 \u003c: 2 \u003c: 3\n\n(* The module [Bwd] is similar to the standard [List] but for backward lists.\n   It has most functions you would expect. For example, the following expression\n   gives the backward list corresponding to [2; 3; 4]. *)\nlet b2 : int bwd = Bwd.map (fun x -\u003e x + 1) b1\n\n(* Same as above, but using [BwdLabels] that mimics [ListLabels] instead. *)\nlet b2' : int bwd = BwdLabels.map ~f:(fun x -\u003e x + 1) b1\n\n(* bwd yoga 1: [\u003c@] for moving elements from a forward list on the right\n   to a backward list on the left. The following gives the backward list\n   corresponding to [1; 2; 3; 4; 5; 6]. *)\nlet b3 : int bwd = b1 \u003c@ [4; 5; 6]\n\n(* bwd yoga 2: [@\u003e] for moving elements from a backward list on the left\n   to a forward list on the right. The following gives the forward list\n   [1; 2; 3; 4; 5; 6; 7; 8; 9]. *)\nlet l4 : int list = b3 @\u003e [7; 8; 9]\n```\n\n## Philosophy\n\n### Cherish the Textual Order\n\nThe idea is that the textual order of elements should never change---what's on the left should stay on the left. We can then rely on the textual order to keep track of semantic order. We might choose different representations (backward or forward lists) to gain efficient access to the elements on one end, but the textual order remains the same. The function `List.rev` violates this invariant because it gives a new list whose elements are in the opposite textual order. For this reason, the following functions (including `List.rev`) are considered ill-typed and should never be used:\n\n- `List.rev`\n- `List.rev_map`\n- `List.rev_map2`\n- `List.rev_append`\n\nOn the other hand, functions in this library (except the general folds) only move elements between forward and backward lists without changing their textual order. The yoga of moving elements should ring a bell for people who have implemented normalization by evaluation (NbE). This simple trick of maintaining textual order seems to have prevented many potential bugs in our proof assistants.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredprl%2Focaml-bwd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredprl%2Focaml-bwd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredprl%2Focaml-bwd/lists"}