{"id":13838023,"url":"https://github.com/polytypic/f-omega-mu","last_synced_at":"2025-08-10T13:09:03.554Z","repository":{"id":45318749,"uuid":"324644898","full_name":"polytypic/f-omega-mu","owner":"polytypic","description":"Fωμ type checker and compiler","archived":false,"fork":false,"pushed_at":"2023-01-28T21:06:08.000Z","size":1875,"stargazers_count":54,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-30T23:03:29.124Z","etag":null,"topics":["equirecursive-types","higher-kinded-types","hobby-project","impredicative-types","structural-types","type-system","wip"],"latest_commit_sha":null,"homepage":"https://polytypic.github.io/f-omega-mu/main","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/polytypic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-26T22:24:03.000Z","updated_at":"2025-04-17T10:15:52.000Z","dependencies_parsed_at":"2023-02-15T19:01:06.272Z","dependency_job_id":null,"html_url":"https://github.com/polytypic/f-omega-mu","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/polytypic/f-omega-mu","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polytypic%2Ff-omega-mu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polytypic%2Ff-omega-mu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polytypic%2Ff-omega-mu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polytypic%2Ff-omega-mu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/polytypic","download_url":"https://codeload.github.com/polytypic/f-omega-mu/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polytypic%2Ff-omega-mu/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269727220,"owners_count":24465407,"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-10T02:00:08.965Z","response_time":71,"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":["equirecursive-types","higher-kinded-types","hobby-project","impredicative-types","structural-types","type-system","wip"],"created_at":"2024-08-04T15:01:33.884Z","updated_at":"2025-08-10T13:09:03.492Z","avatar_url":"https://github.com/polytypic.png","language":"OCaml","funding_links":[],"categories":["OCaml"],"sub_categories":[],"readme":"# Fωμ type checker and compiler\n\nA type checker and compiler\n([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/stream-fusion.fom 'Stream fusion'),\n[\\*](https://polytypic.github.io/f-omega-mu/main#*examples/template-strings.fom 'Template strings'))\nfor Fωμ _restricted to non-nested types_\n([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/errors/nested.fom 'Nested datatypes are disallowed')).\nThis Fωμ variant has\n\n- **structural sum and product types**\n  ([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/lists-of-various-lengths.fom 'Types of lists of various lengths'),\n  [\\*](https://polytypic.github.io/f-omega-mu/main#*examples/generic-folds.fom 'Generic folds')),\n- **join and meet type operators**\n  ([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/finally-tagless.fom 'Finally Tagless')),\n- **equirecursive types**\n  ([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/first-order-and-higher-kinded-lists.fom 'Both first-order and higher-kinded recursive types are allowed'),\n  [\\*](https://polytypic.github.io/f-omega-mu/main#*examples/polymorphic-container-without-pretense.fom 'Polymorphic container without pretense')),\n- **higher-kinded types**\n  ([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/equality-witnesses.fom 'First-class type equality witnesses')),\n  including **type level lambdas** and **kind inference**\n  ([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/type-level-programming.fom 'Type level programming in Fωμ')),\n- **impredicative universal and existential types**\n  ([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/stack-adt.fom 'Stack ADT using an existential type')),\n- **structural subtyping**\n  ([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/aggregate-syntax.fom 'Aggregate syntax'),\n  [\\*](https://polytypic.github.io/f-omega-mu/main#*examples/bounded-subtyping-of-counters.fom 'Bounded subtyping of counters with identity coercions')),\n- **decidable type checking**, and\n- **phase separation**.\n\nThese features make Fωμ relatively well-behaved as well as expressive\n([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/type-gadt-using-eq-witnesses.fom 'GADT type encoding using type equality witnesses'),\n[\\*](https://polytypic.github.io/f-omega-mu/main#*examples/hoas-gadt.fom 'HOAS GADT using Scott encoding'),\n[\\*](https://polytypic.github.io/f-omega-mu/main#*examples/f-omega-self-interpreter.fom 'A self-interpreter for the Fω subset'))\nand also allow a compiler to make good use of untyped compilation targets\n([\\*](https://polytypic.github.io/f-omega-mu/main#*examples/equirecursive-fixpoint-combinator.fom 'Equirecursive applicative fixpoint combinator'),\n[\\*](https://polytypic.github.io/f-omega-mu/main#*examples/object-oriented-sets.fom 'Object-oriented integer set implementations'))\nsuch as JavaScript.\n\nAlthough this is ultimately really intended to serve as an intermediate language\nor elaboration target, the implementation provides both a fairly minimalistic\n[AST](src/main/FomAST/FomAST.mli) and a somewhat more programmer friendly\n[syntax](SYNTAX.md) with some convenience features that are elaborated into the\nAST.\n\nThe implementation also supports dividing a program into multiple files via an\n`import` mechanism for types and values and an `include` mechanism for type\ndefinitions. Value `import`s can be separately compiled. HTTP URLs and relative\npaths are allowed as references.\n\nPlease note that this is a hobby project and still very much Work-in-Progress\nwith tons of missing features, such as\n\n- [partial type inference](https://github.com/polytypic/f-omega-mu/projects/1#card-65813070),\n  and\n- [variance or polarized types](https://github.com/polytypic/f-omega-mu/projects/1#card-74126731),\n\nand probably more\n[bugs](https://github.com/polytypic/f-omega-mu/projects/1#card-65813251) than\none could imagine.\n\n## Next steps\n\n- Try examples in the\n  [online playground](https://polytypic.github.io/f-omega-mu/main#*examples/fact.fom).\n- See the [syntax summary](SYNTAX.md).\n- See [project board](https://github.com/polytypic/f-omega-mu/projects/1).\n\n## Background\n\nThis Fωμ variant is basically _a generalization of_ the type system for Fωμ\\*,\nthat is Fωμ _restricted to first-order recursive types_ of kind `*`, described\nin the article\n\n\u003cblockquote\u003e\n  \u003cdl\u003e\n    \u003cdt\u003e\n      \u003ca href=\"http://ps.informatik.uni-tuebingen.de/research/functors/equirecursion-fomega-popl16.pdf\"\u003e\n        System F-omega with Equirecursive Types for Datatype-generic Programming\n      \u003c/a\u003e\n    \u003c/dt\u003e\n    \u003cdd\u003eby Yufei Cai, Paolo G. Giarrusso, and Klaus Ostermann.\u003c/dd\u003e\n  \u003c/dl\u003e\n\u003c/blockquote\u003e\n\nWhile Fωμ\\* is powerful enough to express regular datatypes, it requires type\nparameters to be hoisted outside of the `μ`. For example, the list type\n\n```\nμlist.λα.opt (α, list α)\n```\n\nneeds to be rewritten as\n\n```\nλα.μlist_1.opt (α, list_1)\n```\n\nBoth of the above types are allowed by this generalized system and are also\nconsidered equivalent as shown in this\n[example](https://polytypic.github.io/f-omega-mu/main#*examples/first-order-and-higher-kinded-lists.fom 'Both first-order and higher-kinded recursive types are allowed').\n\nIn this generalized system, nested types are not allowed. For example,\n\n```\nμnested.λα.(α, nested (α, α))\n```\n\nis disallowed due to the argument `(α, α)` as demonstrated in this\n[example](https://polytypic.github.io/f-omega-mu/main#*examples/errors/nested.fom 'Nested datatypes are disallowed').\n\nDisallowing nested types is sufficient to keep the number of distinct subtrees\nfinite in the infinite expansions of recursive types and to keep type\nequivalence decidable.\n\nFortunately, as conjectured in\n\n\u003cblockquote\u003e\n  \u003cdl\u003e\n    \u003cdt\u003e\u003ca href=\"https://www.cis.upenn.edu/~plclub/blog/2020-12-04-nested-datatypes/\"\u003eDo we need nested datatypes?\u003c/a\u003e\u003c/dt\u003e\n    \u003cdd\u003eby Stephanie Weirich\u003cdd\u003e\n  \u003c/dl\u003e\n\u003c/blockquote\u003e\n\nmany uses of nested datatypes can also be encoded using e.g. GADTs and Fωμ is\npowerful enough to encode many GADTs. Consider, however, the higher-kinded\nnested type\n\n```\nλf.μloop.λx.(x, loop (f x))\n```\n\nthat, when given an `f` and an `x`, would expand to the infinite tree\n\n```\n(x,\n (f x,\n  (f (f x),\n   (f (f (f x)),\n    ...))))\n```\n\nillustrating a process of unbounded computation where `x` could be higher-rank\nand encode arbitrary data. It would seem that this kind of recursion pattern\nwould allow simulating arbitrary computations, which would seem to make type\nequality undecidable. Thus, it would seem that disallowing nested types is not\nonly sufficient, but also necessary to keep type equivalence decidable in the\ngeneral case.\n\n## Why?\n\nGreg Morrisett has called Fω\n[\"the workhorse of modern compilers\"](https://web.archive.org/web/20140917015759/http://www.eecs.harvard.edu/~greg/cs256sp2005/lec16.txt).\nFωμ adds equirecursive types to Fω bringing it closer to practical programming\nlanguages.\n\n[Typed λ-calculi](https://en.wikipedia.org/wiki/Typed_lambda_calculus), and\n[System F](https://en.wikipedia.org/wiki/System_F) in particular, are popular\nelaboration targets for programming languages. Here are a couple of papers using\nsuch an approach:\n\n\u003cblockquote\u003e\n  \u003cdl\u003e\n    \u003cdt\u003e\u003ca href=\"https://people.mpi-sws.org/~rossberg/1ml/\"\u003e1ML — core and modules united\u003c/a\u003e\u003c/dt\u003e\n    \u003cdd\u003eAndreas Rossberg\u003c/dd\u003e\n  \u003c/dl\u003e\n  \u003cdl\u003e\n    \u003cdt\u003e\u003ca href=\"https://arxiv.org/abs/1206.5386\"\u003eElaborating Intersection and Union Types\u003c/a\u003e\n    \u003cdd\u003eJana Dunfield\u003c/dd\u003e\n  \u003c/dl\u003e\n\u003c/blockquote\u003e\n\nPerhaps a practical System Fωμ implementation could serve as a reusable building\nblock or as a forkable boilerplate when exploring such programming language\ndesigns.\n\nHere are a couple of papers about using a Fωμ variant as an IR:\n\n\u003cblockquote\u003e\n  \u003cdl\u003e\n    \u003cdt\u003e\u003ca href=\"https://homepages.inf.ed.ac.uk/wadler/topics/iohk.html\"\u003eUnraveling Recursion: Compiling an IR with Recursion to System F\u003c/a\u003e\u003c/dt\u003e\n    \u003cdd\u003eMichael Peyton Jones, Vasilis Gkoumas, Roman Kireev, Kenneth MacKenzie, Chad Nester, and Philip Wadler\u003cdd\u003e\n  \u003c/dl\u003e\n  \u003cdl\u003e\n    \u003cdt\u003e\u003ca href=\"https://homepages.inf.ed.ac.uk/wadler/topics/iohk.html\"\u003eSystem F in Agda, for fun and profit\u003c/a\u003e\u003c/dt\u003e\n    \u003cdd\u003eJames Chapman, Roman Kireev, Chad Nester, and Philip Wadler\u003cdd\u003e\n  \u003c/dl\u003e\n\u003c/blockquote\u003e\n\nSystem Fω might also be a good language for teaching functional programming and\nmake an interesting object of study on its own:\n\n\u003cblockquote\u003e\n  \u003cdl\u003e\n    \u003cdt\u003e\u003ca href=\"https://dl.acm.org/doi/abs/10.1145/3342713\"\u003eLambda: the ultimate sublanguage (experience report)\u003c/a\u003e\u003c/dt\u003e\n    \u003cdd\u003eJeremy Yallop, Leo White\u003cbr\u003e\u003ca href=\"https://github.com/ocamllabs/fomega\"\u003eSystem Fω interpreter for use in Advanced Functional Programming course\u003c/a\u003e\u003cdd\u003e\n  \u003c/dl\u003e\n  \u003cdl\u003e\n    \u003cdt\u003e\u003ca href=\"https://dl.acm.org/doi/abs/10.1145/2837614.2837623\"\u003eBreaking Through the Normalization Barrier: A Self-Interpreter for F-omega\u003c/a\u003e\u003c/dt\u003e\n    \u003cdd\u003eMatt Brown, Jens Palsberg\u003cdd\u003e\n  \u003c/dl\u003e\n\u003c/blockquote\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolytypic%2Ff-omega-mu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpolytypic%2Ff-omega-mu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolytypic%2Ff-omega-mu/lists"}