moved TODOs to forgejo issues

This commit is contained in:
William Ball 2024-12-05 19:48:34 -08:00
parent 7e3a347485
commit 72e695a381

View file

@ -157,108 +157,3 @@ Then running =perga equality.pg= yields the following output.
Cannot unify 'A -> *' with 'P x' when evaluating 'Hxy Hx' Cannot unify 'A -> *' with 'P x' when evaluating 'Hxy Hx'
#+end_src #+end_src
This indicates that, when evaluating =Hxy Hx=, it was expecting something of type =A -> *=, but instead found something of type =P x=. Since =P= is type =A -> *=, we can then realize that we forgot the =P=. This indicates that, when evaluating =Hxy Hx=, it was expecting something of type =A -> *=, but instead found something of type =P x=. Since =P= is type =A -> *=, we can then realize that we forgot the =P=.
* Future Goals
** Substantive
*** TODO Sections
Coq-style sections would be very handy, and probably /relatively/ easy to implement (compared to everything else on this todo list), especially now that we have an [[Multiple levels of AST][intermediate representation]].
*** TODO Inference
Not decidable, but I might be able to implement some basic unification algorithm, or switch to bidirectional type checking. This isn't super necessary though, I find leaving off the types of arguments to generally be a bad idea, but in some cases it can be handy, especially not at the top level.
*** TODO Implicits
Much, much more useful than [[Inference][inference]], implicit arguments would be amazing. It also seems a lot more complicated, but any system for dealing with implicit arguments is far better than none.
*** TODO Module System
A proper module system would be wonderful. To me, ML style modules with structures, signatures, and functors seems like the right way to handle algebraic structures for a relatively simple language, rather than records (or, worse, a bunch of =and='s like I currently have; especially painful without [[Implicits][implicits]]) or type classes (probably much harder, but could be nicer), but any way of managing scope, importing files, etc. is a necessity. The [[https://www.cambridge.org/core/services/aop-cambridge-core/content/view/B573FA00832D55D4878863DE1725D90B/S0956796814000264a.pdf/f-ing-modules.pdf][F-ing modules]] paper is probably a good reference. Now that I have an [[Multiple levels of AST][intermediate representation]], following in /F-ing modules/'s footsteps and implementing modules purely through elaboration should be possible.
*** DONE Universes?
Not super necessary, but occasionally extremely useful. Could be fun, idk.
I was looking into bidirectional typing and came across a description of universes. It turned out to be much easier to implement than I was expecting, so I figured why not and added universes. So now =* : *1 : *2 : *3 : ...=. However, they're basically useless without [[Universe polymorphism][universe polymorphism]] of some kind.
Also, everything ends up impredicative (no =* : *=, but quantifying over =*i= still leaves you in =*i=), and my implementation of impredicativity feels a little sketchy. There might be paradoxes lurking. It would be easy to switch it over to being predicative, but, without inductive types or at least more built-in types, logical connectives can only be defined impredicatively, so that will have to wait until we have inductive definitions.
I have since followed in Coq's footsteps and switched universe hierarchies to =* : □ : □₁ : □₂ : □₃ : ...=, where all the =□ᵢ= are predicative and =*= is impredicative (analogous to =Prop= and =Type=). For now at least, we definitely need at least the lowest sort to be impredicative to allow for impredicative definitions of connectives.
*** TODO Universe polymorphism
I have [[Universes?][universes]], but without universe polymorphism, they're basically useless, or at least I am unable to find a practical use for them. (When would you want to quantify over e.g. kinds specifically?)
*** TODO Sigma and sum types
While not full [[Inductive Definitions][inductive definitions]], builtin sigma and sum types (and probably a unit type to complete the algebra) would make predicative universes actually possible to work in, and generally make working with conjunctions, disjunctions, and existentials much easier (especially with pattern matching). Record types could then likely follow as syntax sugar for a bunch of dependent pairs dealt with by the elaborator, making for easier definitions of e.g. algebraic structures.
*** TODO Inductive Definitions
This is definitely a stretch goal. It would be cool though, and would turn this proof checker into a much more competent programming language. It's not necessary for the math, but inductive definitions let you leverage computation in proofs, which is amazing. They also make certain definitions way easier, by avoiding needing to manually stipulate elimination rules, including induction principles, and let you keep more math constructive and understandable to the computer.
** Cosmetic/usage/technical
*** TODO Prettier pretty printing
Right now, everything defaults to one line, which can be a problem with how large the proof terms get. Probably want to use [[https://hackage.haskell.org/package/prettyprinter][prettyprinter]] to be able to nicely handle indentation and line breaks.
*** TODO Better repl
The repl is decent, probably the most fully-featured repl I've ever made, but implementing something like [[https://abhinavsarkar.net/posts/repling-with-haskeline/][this]] would be awesome.
*** TODO Improve error messages
Error messages are decent, but a little buggy. Syntax error messages are pretty ok, but could have better labeling. The type check error messages are decent, but could do with better location information. Right now, the location defaults to the end of the current definition, which is often good enough, but more detail can't hurt. The errors are generally very janky and hard to read. Having had quite a bit of practice reading them now, they actually provide very useful information, but could be made *a lot* more readable.
Since adding [[Multiple levels of AST][an intermediate AST]], the error messages have gotten much worse. This is pretty urgent now.
*** TODO Document library code
Low priority, as I'm the only one working on this, I'm working on it very actively, and things will continue rapidly changing, but I'll want to get around to it once things stabilize, before I forget how everything works.
*** TODO Add versions to =perga.cabal= and/or nixify
Probably a smart idea.
*** TODO More incremental parsing/typechecking
Right now, if there's a failure, everything just stops immediately. More incremental parsing/typechecking could pave the way for more interactivity, e.g. development with holes, an LSP server, etc., not to mention better error messages.
*** DONE Multiple levels of AST
Added a couple types representing an intermediate representation, as well as a module responsible for elaboration (basically a function from these intermediate types to =Expr=). This /drastically/ simplified the parser, now that it is not responsible for converting to de Bruijn indices, handling the environment, and type checking all in addition to parsing. However, now that type checking is out of the parser, we lost location information for errors, making [[Improve error message][better error messages]] much more important now. I have some ideas for getting location information (and more accurate location information, instead of always pointing to the end of the most relevant definition), which should drastically improve the error messages.
*** TODO Improve type checking algorithm
I'm proud that I just kinda made up a working type checking algorithm, but it is clearly quite flawed. Even assuming no need to check beta equivalence, I'm pretty sure that this algorithm is approximately exponential in the length of a term, which is pretty terrible. It hasn't been a huge problem, but type checking just the term =R2_sub_R= in [[./examples/peano.pg]] takes about 1.5 seconds. Performance could easily be drastically improved with some memoization, but upgrading to an off-the-shelf bidirectional type checking algorithm seems like a good idea in general. Another problem with my current type checking algorithm is that it is very inflexible (e.g. adding optional return type ascriptions in functions, or type ascriptions in =let= bindings is currently impossible, while trivial to add with bidirectional type checking). I also have no idea how to add [[Inference][type inference]] or [[Implicits][implicits]] with how things are currently structured. A more flexible type checking algorithm, likely together with [[Multiple levels of AST][multiple levels of AST]], makes it seem more possible.
*** TODO Alternate syntax
I've had a bunch of ideas for a more mathematician-friendly syntax bouncing around my head for a while. Implementing one of them would be awesome, but probably quite tricky.
Something like
#+begin_src text
Theorem basic (S : *) (P : S → *) :
(∀ (x : S), P x → Q x) → (∀ (x : S), P x) → ∀ (x : S), Q x.
Proof
1. Suppose ∀ (x : S), P x → Q x
2. Suppose ∀ (x : S), P x
3. Let x : S
4. P x by [2 x]
5. Q x by [1 x 4]
Qed
#+end_src
I think could be reliably translated into
#+begin_src
basic (S : *) (P : S → *) : (Π (x : S), P x → Q x) → (Π (x : S), P x) → Π (x : S), Q x :=
fun (a1 : Π (x : S), P x → Q x) ⇒
fun (a2 : Π (x : S), P x) ⇒
fun (x : S) ⇒
a1 x (a2 x);
#+end_src
and is more intuitively understandable to a mathematician not familiar with type theory, while the latter would be utter nonsense.
I'm imagining the parser could be chosen based on the file extension or something. Some way to mix the syntaxes could be nice too.
*** TODO Infix/misfix operators
Infix/misfix operators would be very nice and make =perga= look more normal. It's funny, at the moment it looks a lot like a lisp, even though it's totally not. Here's an excerpt from the proof that addition is commutative that looks particularly lispy.
#+begin_src
(eq_trans nat (plus n (suc m)) (suc (plus n m)) (plus (suc m) n)
(plus_s_r n m)
(eq_trans nat (suc (plus n m)) (suc (plus m n)) (plus (suc m) n)
(eq_cong nat nat (plus n m) (plus m n) suc IH)
(eq_sym nat (plus (suc m) n) (suc (plus m n)) (plus_s_l m n))))
#+end_src
*** DONE treesitter parser and/or emacs mode
There's a [[https://forgejo.ballcloud.cc/wball/tree-sitter-perga][tree-sitter parser]] and [[https://forgejo.ballcloud.cc/wball/perga.nvim][neovim plugin]] available now, but no emacs-mode.
*** TODO TUI
This is definitely a stretch goal, and I'm not sure how good of an idea it would be, but I'm imagining a TUI split into two panels. On the left you can see the term you are building with holes in it. On the right you have the focused hole's type as well as the types of everything in scope (like Coq and Lean show while you're in the middle of a proof). Then you can interact with the system by entering commands (e.g. =intros=, =apply=, etc.) which changes the proof term on the left. You'd also just be able to type in the left window as well, and edit the proof term directly. This way you'd get the benefits of working with tactics, making it way faster to construct proof terms, and the benefits of working with proof terms directly, namely transparency and simplicity. I'll probably want to look into [[https://hackage.haskell.org/package/brick][brick]] if I want to make this happen.