{"id":16613346,"url":"https://github.com/yallop/metaocaml-letrec","last_synced_at":"2025-09-28T17:31:07.050Z","repository":{"id":54555182,"uuid":"114361731","full_name":"yallop/metaocaml-letrec","owner":"yallop","description":"flexible 'let rec' generation for MetaOCaml","archived":false,"fork":false,"pushed_at":"2023-06-30T16:33:41.000Z","size":31,"stargazers_count":26,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-11T08:13:57.608Z","etag":null,"topics":["metaocaml","recursion","staging"],"latest_commit_sha":null,"homepage":"","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yallop.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","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":"2017-12-15T11:06:06.000Z","updated_at":"2024-11-07T09:05:10.000Z","dependencies_parsed_at":"2022-08-13T19:31:14.960Z","dependency_job_id":null,"html_url":"https://github.com/yallop/metaocaml-letrec","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yallop%2Fmetaocaml-letrec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yallop%2Fmetaocaml-letrec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yallop%2Fmetaocaml-letrec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yallop%2Fmetaocaml-letrec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yallop","download_url":"https://codeload.github.com/yallop/metaocaml-letrec/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234460526,"owners_count":18836839,"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","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":["metaocaml","recursion","staging"],"created_at":"2024-10-12T01:46:51.927Z","updated_at":"2025-09-28T17:31:07.045Z","avatar_url":"https://github.com/yallop.png","language":"OCaml","funding_links":[],"categories":[],"sub_categories":[],"readme":"# metaocaml-letrec: flexible 'let rec' generation\n\n![GitHub Actions status](https://github.com/yallop/metaocaml-letrec/workflows/test/badge.svg)\n\nIn typed MetaML-based systems such as MetaOCaml it is difficult or impossible to generate mutually-recursive binding groups whose size is not known in advance.  For example, suppose (following an example of Neil Jones expounded by [Oleg][oleg]) that you want to [specialize the Ackermann function][oleg-ltu-ackermann-comment]\n\n```ocaml\nlet rec ack m n =\n   if m = 0 then n+1 else\n   if n = 0 then ack (m-1) 1 else\n   ack (m-1) (ack m (n-1))\n```\n\nwith the first argument equal to `2`.  Ideally, you might like to generate the following code, with three mutually recursive bindings and all the recursive calls specialized:\n\n```ocaml\nlet rec ack_2 n = if n = 0 then ack_1 1 else  ack_1 (ack_2 (n-1))\n    and ack_1 n =  if n = 0 then ack_0 1 else  ack_0 (ack_1 (n-1))\n    and ack_0 n =  n+1\n```\n\nWith `metaocaml-letrec` you can generate exactly that code, modulo naming, by [annotating the original definition of `ack` as follows](lib_test/ackermann.ml) (and passing the argument `2`):\n\n```ocaml\n  let%staged rec ack m =\n    .\u003c fun n -\u003e .~(if m = 0 then .\u003cn+1\u003e. else\n                .\u003c if n = 0 then .~(ack (m-1)) 1 else\n                   .~(ack (m-1)) (.~(ack m) (n-1)) \u003e.)\u003e.\n```\n\nand, in general, `ack n` will generate a `let rec` group of `n+1` bindings.\n\nMore generally, `metocaml-letrec` treats a `let rec` binding as an indexed family, where the argument to the generating function is the index.  In the `ack` example, the index `m` is a simple integer; in general it may be a richer object, making it possible to generate arbitrary patterns of recursion, including\n\n* [nested let rec bindings](lib_test/nested.ml)\n* [polymorphic recursion](lib_test/polymorphic.ml)\n* [recursion with non-function values](lib_test/recursive_values.ml)\n* recursion where the bindings have different types\n\nand many more examples.\n\n### Installation\n\n`metaocaml-letrec` works on various versions of [BER MetaOCaml][ber-metaocaml], which are [available via `OPAM`][metaocaml-switch]:\n\n```\nopam switch install 4.14.1+BER\neval $(opam env)\n```\n\nWithin this `4.14.1+BER` switch the `metaocaml-letrec` package can be installed as follows:\n\n```\nopam remote add metaocaml git+https://github.com/metaocaml/metaocaml-opam.git\nopam install letrec\n```\n\n### Further reading\n\nThe following paper has more details about the design and implementation of `metaocaml-letrec`:\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;[Generating mutually recursive definitions][pepm19-paper]  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;Jeremy Yallop and Oleg Kiselyov  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;[PEPM 2019][pepm-2019]\n\n[oleg-ltu-ackermann-comment]: http://lambda-the-ultimate.org/node/4039#comment-61431\n[oleg]: http://okmij.org/ftp/\n[ber-metaocaml]: http://okmij.org/ftp/ML/MetaOCaml.html\n[metaocaml-switch]: https://github.com/ocaml/opam-repository/blob/master/packages/ocaml-variants/ocaml-variants.4.14.1+BER/opam\n[pepm-2019]: https://popl19.sigplan.org/track/pepm-2019-papers\n[pepm19-paper]: https://www.cl.cam.ac.uk/~jdy22/papers/generating-mutually-recursive-definitions-short-paper.pdf\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyallop%2Fmetaocaml-letrec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyallop%2Fmetaocaml-letrec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyallop%2Fmetaocaml-letrec/lists"}