https://github.com/polytypic/f-omega-mu
Fωμ type checker and compiler
https://github.com/polytypic/f-omega-mu
equirecursive-types higher-kinded-types hobby-project impredicative-types structural-types type-system wip
Last synced: 10 months ago
JSON representation
Fωμ type checker and compiler
- Host: GitHub
- URL: https://github.com/polytypic/f-omega-mu
- Owner: polytypic
- License: mit
- Created: 2020-12-26T22:24:03.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2023-01-28T21:06:08.000Z (over 3 years ago)
- Last Synced: 2025-04-30T23:03:29.124Z (about 1 year ago)
- Topics: equirecursive-types, higher-kinded-types, hobby-project, impredicative-types, structural-types, type-system, wip
- Language: OCaml
- Homepage: https://polytypic.github.io/f-omega-mu/main
- Size: 1.79 MB
- Stars: 54
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Fωμ type checker and compiler
A type checker and compiler
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/stream-fusion.fom 'Stream fusion'),
[\*](https://polytypic.github.io/f-omega-mu/main#*examples/template-strings.fom 'Template strings'))
for Fωμ _restricted to non-nested types_
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/errors/nested.fom 'Nested datatypes are disallowed')).
This Fωμ variant has
- **structural sum and product types**
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/lists-of-various-lengths.fom 'Types of lists of various lengths'),
[\*](https://polytypic.github.io/f-omega-mu/main#*examples/generic-folds.fom 'Generic folds')),
- **join and meet type operators**
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/finally-tagless.fom 'Finally Tagless')),
- **equirecursive types**
([\*](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'),
[\*](https://polytypic.github.io/f-omega-mu/main#*examples/polymorphic-container-without-pretense.fom 'Polymorphic container without pretense')),
- **higher-kinded types**
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/equality-witnesses.fom 'First-class type equality witnesses')),
including **type level lambdas** and **kind inference**
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/type-level-programming.fom 'Type level programming in Fωμ')),
- **impredicative universal and existential types**
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/stack-adt.fom 'Stack ADT using an existential type')),
- **structural subtyping**
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/aggregate-syntax.fom 'Aggregate syntax'),
[\*](https://polytypic.github.io/f-omega-mu/main#*examples/bounded-subtyping-of-counters.fom 'Bounded subtyping of counters with identity coercions')),
- **decidable type checking**, and
- **phase separation**.
These features make Fωμ relatively well-behaved as well as expressive
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/type-gadt-using-eq-witnesses.fom 'GADT type encoding using type equality witnesses'),
[\*](https://polytypic.github.io/f-omega-mu/main#*examples/hoas-gadt.fom 'HOAS GADT using Scott encoding'),
[\*](https://polytypic.github.io/f-omega-mu/main#*examples/f-omega-self-interpreter.fom 'A self-interpreter for the Fω subset'))
and also allow a compiler to make good use of untyped compilation targets
([\*](https://polytypic.github.io/f-omega-mu/main#*examples/equirecursive-fixpoint-combinator.fom 'Equirecursive applicative fixpoint combinator'),
[\*](https://polytypic.github.io/f-omega-mu/main#*examples/object-oriented-sets.fom 'Object-oriented integer set implementations'))
such as JavaScript.
Although this is ultimately really intended to serve as an intermediate language
or elaboration target, the implementation provides both a fairly minimalistic
[AST](src/main/FomAST/FomAST.mli) and a somewhat more programmer friendly
[syntax](SYNTAX.md) with some convenience features that are elaborated into the
AST.
The implementation also supports dividing a program into multiple files via an
`import` mechanism for types and values and an `include` mechanism for type
definitions. Value `import`s can be separately compiled. HTTP URLs and relative
paths are allowed as references.
Please note that this is a hobby project and still very much Work-in-Progress
with tons of missing features, such as
- [partial type inference](https://github.com/polytypic/f-omega-mu/projects/1#card-65813070),
and
- [variance or polarized types](https://github.com/polytypic/f-omega-mu/projects/1#card-74126731),
and probably more
[bugs](https://github.com/polytypic/f-omega-mu/projects/1#card-65813251) than
one could imagine.
## Next steps
- Try examples in the
[online playground](https://polytypic.github.io/f-omega-mu/main#*examples/fact.fom).
- See the [syntax summary](SYNTAX.md).
- See [project board](https://github.com/polytypic/f-omega-mu/projects/1).
## Background
This Fωμ variant is basically _a generalization of_ the type system for Fωμ\*,
that is Fωμ _restricted to first-order recursive types_ of kind `*`, described
in the article
-
System F-omega with Equirecursive Types for Datatype-generic Programming
- by Yufei Cai, Paolo G. Giarrusso, and Klaus Ostermann.
While Fωμ\* is powerful enough to express regular datatypes, it requires type
parameters to be hoisted outside of the `μ`. For example, the list type
```
μlist.λα.opt (α, list α)
```
needs to be rewritten as
```
λα.μlist_1.opt (α, list_1)
```
Both of the above types are allowed by this generalized system and are also
considered equivalent as shown in this
[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').
In this generalized system, nested types are not allowed. For example,
```
μnested.λα.(α, nested (α, α))
```
is disallowed due to the argument `(α, α)` as demonstrated in this
[example](https://polytypic.github.io/f-omega-mu/main#*examples/errors/nested.fom 'Nested datatypes are disallowed').
Disallowing nested types is sufficient to keep the number of distinct subtrees
finite in the infinite expansions of recursive types and to keep type
equivalence decidable.
Fortunately, as conjectured in
- Do we need nested datatypes?
- by Stephanie Weirich
-
many uses of nested datatypes can also be encoded using e.g. GADTs and Fωμ is
powerful enough to encode many GADTs. Consider, however, the higher-kinded
nested type
```
λf.μloop.λx.(x, loop (f x))
```
that, when given an `f` and an `x`, would expand to the infinite tree
```
(x,
(f x,
(f (f x),
(f (f (f x)),
...))))
```
illustrating a process of unbounded computation where `x` could be higher-rank
and encode arbitrary data. It would seem that this kind of recursion pattern
would allow simulating arbitrary computations, which would seem to make type
equality undecidable. Thus, it would seem that disallowing nested types is not
only sufficient, but also necessary to keep type equivalence decidable in the
general case.
## Why?
Greg Morrisett has called Fω
["the workhorse of modern compilers"](https://web.archive.org/web/20140917015759/http://www.eecs.harvard.edu/~greg/cs256sp2005/lec16.txt).
Fωμ adds equirecursive types to Fω bringing it closer to practical programming
languages.
[Typed λ-calculi](https://en.wikipedia.org/wiki/Typed_lambda_calculus), and
[System F](https://en.wikipedia.org/wiki/System_F) in particular, are popular
elaboration targets for programming languages. Here are a couple of papers using
such an approach:
- 1ML — core and modules united
- Andreas Rossberg
-
Elaborating Intersection and Union Types
- Jana Dunfield
Perhaps a practical System Fωμ implementation could serve as a reusable building
block or as a forkable boilerplate when exploring such programming language
designs.
Here are a couple of papers about using a Fωμ variant as an IR:
- Unraveling Recursion: Compiling an IR with Recursion to System F
- Michael Peyton Jones, Vasilis Gkoumas, Roman Kireev, Kenneth MacKenzie, Chad Nester, and Philip Wadler
-
- System F in Agda, for fun and profit
- James Chapman, Roman Kireev, Chad Nester, and Philip Wadler
-
System Fω might also be a good language for teaching functional programming and
make an interesting object of study on its own:
- Lambda: the ultimate sublanguage (experience report)
- Jeremy Yallop, Leo White
System Fω interpreter for use in Advanced Functional Programming course-
- Breaking Through the Normalization Barrier: A Self-Interpreter for F-omega
- Matt Brown, Jens Palsberg
-