390 karma · joined December 22, 2011
All of this falls away in dependent type theory you can represent the whole language with a class of pesudo-terms. For example the core expressions can be captured by the below grammar:
term := x
| f x
| forall (x : Type), B x
| lambda (x : A), e
| Type
Type checking (not inference) is straight forward to implement for these theories and can be done in about a page or two of code. Of course "elaboration" or "type-inference" for these theories can be much more complex, but Haskell's isn't simple either. The most recent publication on the TI algorithm is roughly 80 pages.In practice you spend way more time writing proofs in these system then doing anything else. There is evidence that we don't need to limit the expressive power of our logics, just design appropriate automation for the logic. Lean, a new ITT based theorem prover from MSR, has been focused on building automation for type theory. It already has promising results that formal methods techniques can be scaled to type theory (see the website for more information on recent work).
First, type theory based proof assistants (like Coq) and model checkers are very different tools with very different guarantees. Most model checkers are used for proving properties about finite models and can not reason about infinite structures.
A type theory with inductive types gives one a mechanism for constructing inductive structures, and the ability to write proofs about them.
I am not sure how you have equated denotational semantics and type theory but there is no inherent connection, denotational semantics are just one way to give a language semantics. One can use them to describe the computational behavior of your type theory, but they are not fundamental.
Category theory and type theory have a cool isomorphism between them, but otherwise can be completely silo'd you can be quite proficient in type theory and never touch or understand any category theory at all.
On the subject of TLA+, Leslie Lamport loves to talk about "ordinary mathematics" but he just chose a different foundational mathematics to build his tool with, type theory is an alternative formulation in this regard. One that is superior in some ways since the language for proof, and programming is one and the same and does not require strange stratification or layering of specification and implementation languages.
Another issue with many of these model based tools is the so called "formality gap" building a clean model of your program and then proving properties is nice, but without a connection to your implementation the exercise has questionable value. Sure, with distributed systems for example, writing out a model of your protocol can help find design bugs, but it will not stop you from incorrectly implementing said protocol. In the distributed systems even with testing, finding safety violations in practice is hard, and many of them can occur silently.
Proof assistants like Coq make doing this easier since your implementation and proof live side by side, and you can reason directly about your implementation instead of a model. If you don't like dependently typed functional languages you can check out tools like Dafny which provide a similar work style, but with more automation and imperative programming constructs.
> This formulation serves as the basis for most formal reasoning of computer programs.
On this statement I'm not sure what community you come from, but much of the work going on in the research community is using things like SMT which exposes SAT and a flavor of first order logic, an HOL based system like Isabelle, or type theory, very few people use tools like set theory to reason about programs.
> Engineers, however, already have nearly all the math they need to reason about programs and algorithm in the common mathematical way (they just may not know it, which is why I so obnoxiously bring it up whenever I can, to offset the notion that is way overrepresented here on HN that believes that "PFP is the way to mathematically reason about programs".
Finally this statement is just plain not true, abstractly its easy to hand way on paper about the correctness of your algorithm. I encourage you to show me the average engineer who can pick up a program and prove non-trivial properties about its implementation, even on paper. I wager even proving the implementation of merge sort correct would prove too much. I've spent the last year implementing real, low-level systems using type theory, and this stuff is hard if you can show me a silver bullet I would be ecstatic, but any approach with as much power and flexibility is at least as hard to use.
Its not that "PFP" (and its not PFP, its type theory that makes this possible) is the "right way" to reason about programs but that it makes it possible to reason about programs. For example, how do you prove a loop invariant in Python? how would you even start? I know of a few ways to do this, but most provide a weaker guarantee then you would type theory version would, and requires a large trusted computing base.
These are just the areas I work in, its very hard to making sweeping statement about CS as a full field since it is very diverse sub-community to sub-community.
Nearly every language has continued to repeat Tony Hoare's "billion dollar" mistake of allowing null to inhabit any type. I think approaches like Rust's and Swift's are steps to stamp out something that never should of existed in the first place.
You can also adopt automated verification techniques that can prove strong properties about a system automatically.
My recent work has been on a verified JIT compiler and having to write tactics and lemmas to deal with facts about bit vectors seems stupid when SMT solvers are particularly good at this kind of reasoning.
I think it is also important to recognize that all compilers have this problem and they all stabilize over time. It is an issue orthogonal of safety. These aren't segmentation faults or some kind of memory error but the compiler signaling an internal invariant was violated.
This can happen easily because we are writing a very large program that reads user input, interprets it, and tries to emit a program.
This can happen in multiple situations. One example is the compiler may have a logic bug that violates an internal invariant resulting in an ICE (instead of emitting incorrect code).
Other times it is as simple as the code we have been given is invalid and the error wasn't properly handled, and you end up seeing it in a non-user friendly way (as an ICE).
We are working hard to move the compiler to a more modern, robust design as soon as possible but even with a great design it will be an iterative process that we continue to do over the lifetime of the language, just like everyone else.
I want to be clear that I'm not hating on Idris I love the goals of the project and am probably one of the few people outside the core contributors who has written a backend for the compiler, but you can't really compare a production quality compiler with a full time team of 10 or so to a research compiler worked on by researchers (who have different goals) and volunteers.
Edit: To clarify for this reason I could see why it would be cool to be able to write some critical code in Idris and extract to Rust where you could get performance and tooling for the rest of your application.
The important take away implications are: - you can not implement a trait defined in another crate for a type defined in another crate, unless the trait is parametrized by a type from the current crate - you can't define overlapping implementations
My GPA looks "low" around a 3.3 cumulative (I have lots of C's in things I deemed unimportant) but I have a relatively high CS GPA (3.8-3.9), took many graduate classes during undergrad, worked at startups, consulted, did multiple years of research resulting in two publications with 2-3 more in the pipeline, worked on open source, gave talks at workshops and software engineering conferences, TAed, constructed two student led courses, etc.
It seems the most important thing is to demonstrate your ability to work as a researcher (your primary role as a CS graduate student) trumps all in graduate admissions, but that is just my 2 cents.
As a side note although clunky HKTs are encodable in Rust and I plan on implementing them natively once we have landed a stable version of 1.0.