{"id":40924618,"url":"https://github.com/mbarbin/nofunc-keyed","last_synced_at":"2026-01-22T03:39:01.288Z","repository":{"id":328153427,"uuid":"1111898930","full_name":"mbarbin/nofunc-keyed","owner":"mbarbin","description":"Keyed data structures adapted from OCaml Stdlib but no functors","archived":false,"fork":false,"pushed_at":"2026-01-13T15:12:35.000Z","size":90,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-13T18:07:01.791Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mbarbin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"COPYING.HEADER","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-07T20:51:28.000Z","updated_at":"2026-01-13T15:12:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mbarbin/nofunc-keyed","commit_stats":null,"previous_names":["mbarbin/nofunc-keyed"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mbarbin/nofunc-keyed","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbarbin%2Fnofunc-keyed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbarbin%2Fnofunc-keyed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbarbin%2Fnofunc-keyed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbarbin%2Fnofunc-keyed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mbarbin","download_url":"https://codeload.github.com/mbarbin/nofunc-keyed/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbarbin%2Fnofunc-keyed/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28653275,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"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":[],"created_at":"2026-01-22T03:39:00.563Z","updated_at":"2026-01-22T03:39:01.281Z","avatar_url":"https://github.com/mbarbin.png","language":"OCaml","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nofunc-keyed\n\n## Introduction\n\nThis repo implements OCaml packages for common data structures with elements used as keys:\n\n- Map\n- Set\n- Hash-table\n- Hash-set\n\nThe code is derived from the OCaml Stdlib, and adapted to remove the use of functors. Some may know this as a style used in the `Base` library which also relates to designs inspired by `modular-explicit`.\n\n## Description\n\nThese data structures require functions operating on a key type, typically `hash`, `equal` or `compare`. Instead of accessing then from a functor argument, the functions that create new structures take them from a first-class module passed as a mandatory argument in first position.\n\n**Functorized (stdlib):**\n```ocaml\nmodule Int_set = Stdlib.Set.Make (Int)\nlet (s : Int_set.t) = Int_set.of_list [ 1; 2; 3 ]\n```\n\n**Nofunc (this project)**:\n```ocaml\nmodule Set = Nofunc_set.Set\nlet (s : int Set.t) = Set.of_list (module Int) [ 1; 2; 3 ]\n```\n\nNote that in the `nofunc` version, the keys are type parameters.\n\nThe required functions are stored *inside the structure* for later use by the functions that need it. So for example here, `Int.compare` will be stored as a field inside that `s` value.\n\n### Dynamic Resolution of Conflicting Key Functions\n\nIn `Nofunc`, the code raises an exception when attempting to operate on multiple values that have been created using different key functions.\n\n```ocaml\nmodule Set = Nofunc_set.Set\n\nlet%expect_test \"different compare\" =\n  let module String2 = struct\n    type t = string\n\n    (* The compare function is reversed! *)\n    let compare a b = String.compare b a\n  end\n  in\n  let s1 = Set.of_list (module String) [ \"a\"; \"b\" ] in\n  let s2 = Set.of_list (module String2) [ \"c\"; \"b\" ] in\n  print_dyn (Set.to_dyn Dyn.string s1);\n  [%expect {| set { \"a\"; \"b\" } |}];\n  print_dyn (Set.to_dyn Dyn.string s2);\n  [%expect {| set { \"c\"; \"b\" } |}];\n  let () =\n    match Set.union s1 s2 with\n    | (_ : string Set.t) -\u003e assert false\n    | exception e -\u003e print_string (Printexc.to_string e)\n  in\n  [%expect {| Invalid_argument(\"Sets have different compare functions.\") |}];\n  ()\n;;\n```\n\nThis exception indicates a programming error that must be fixed.\n\nThese principles generalize to the other data structures available here besides `Set`.\n\n### Style \u0026 API\n\nThe packages come in two flavors, `std` and `non-std`.\n\n- The packages `nofunc-std*` follow closely the naming and API from the OCaml Stdlib.\n- The packages `nofunc-*` (without the `std` prefix) build on the general principles mentioned here, while making some additional opinionated decisions based on the author's personal preferences.\n\n## Motivations\n\nWe believe that avoiding functors can be ergonomic in some cases and we think that these libraries could be useful in projects that do not depend on `Base`.\n\nWe're experimenting with the non-standard versions in personal projects.\n\n## License\n\n`LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception`\n\n## Status\n\n:construction: We're currently building this project and we'll update this section once we're done with that initial phase.\n\n## Acknowledgements\n\nThere is very little if any original content in this repo. We re-packaged code from existing sources to make the libraries easily available for other projects.\n\nWe are very thankful to the work we've been able to build upon here. We're listing these sources below.\n\n### OCaml Stdlib \u0026 INRIA\n\nhttps://github.com/ocaml/ocaml\n\nThe implementation is based on copies of original modules from the OCaml Stdlib, with minor changes required by this project:\n\n- Hashtbl\n- Map\n- Set\n\nThe license of ocaml is included [here](third-party-license/ocaml/ocaml/LICENSE).\n\n### Base \u0026 Jane Street\n\nhttps://github.com/janestreet/base\n\nSources of inspirations for this project include the modules and interfaces of similar keyed modules from the `Base` library.\n\nThe license of base is included [here](third-party-license/janestreet/base/LICENSE.md).\n\n### Stdune\n\nhttps://github.com/ocaml/dune\n\nAnother source of inspiration for this project was similar keyed modules from `dune`'s standard library `stdune`.\n\nThe license of dune is included [here](third-party-license/ocaml/dune/LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbarbin%2Fnofunc-keyed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmbarbin%2Fnofunc-keyed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbarbin%2Fnofunc-keyed/lists"}