Proof-Oriented Programming Languages
- Proof-Oriented Programming Languages are systems that integrate executable code, formal specifications, and correctness proofs into a unified development process.
- They utilize diverse architectures—such as SMT-assisted, ML-like, and imperative embeddings—to seamlessly combine programming with formal verification.
- POPLs enhance software assurance by enabling integrated synthesis, automated proof verification, and even AI-assisted proof development for optimized reliability.
Searching arXiv for recent and foundational papers on proof-oriented programming languages to ground the article. arxiv_search query: "proof-oriented programming languages F* Verus GallinaC PML 2 ATS POPLs" arxiv_search query: "\"proof-oriented programming\" language F* Verus GallinaC" Proof-oriented programming languages (POPLs) are programming languages and verification environments in which executable code, formal specifications, and correctness proofs are expressed in a unified setting, so that correctness is checked as part of program construction rather than as a wholly external activity. Across the literature, the term covers several technical families: SMT-assisted languages such as F* and Verus, ML-like languages that treat proofs as terminating programs, frameworks that separate statics from dynamics while allowing theorem-proving during type-checking, and imperative embeddings inside proof assistants for low-level verified code (Jain et al., 1 Aug 2025). What unifies these systems is not a single implementation technique, but a common design goal: to make program construction, specification, and verification part of one formal workflow (Lepigre, 2019).
1. Foundational ideas
A central intellectual source for POPLs is the Curry–Howard correspondence, understood not merely as an analogy between proofs and programs, but as a claim that, in an adequate language, “the activity of writing programs is equivalent to the activity of writing a formal proof” (Emerich, 2016). This formulation motivates languages in which types are specifications, terms are proofs, and verification is performed by the language’s own typing or proof machinery. In F*, for example, a term’s type can encode a semantic property stronger than simple shape information, so that proving correctness amounts to constructing a term with a sufficiently precise type (Chakraborty et al., 2024).
A stronger proof-theoretic version appears in “Programs as proofs,” which argues that every programming construct can be given a rule-like semantics, so that programs become structured derivations and a programming language can be regarded as a theory whose operations act as axioms (Steensgaard-Madsen, 2015). On that view, proof orientation is not only about attaching propositions to terms; it is about designing language constructs so that application and composition already have deductive meaning.
A complementary semantic lineage appears in “Theory of Programs,” which treats a program over a state space as a pair , with a postcondition relation and a precondition set, and derives refinement, feasibility, invariants, loops, and concurrency laws from elementary set theory rather than postulating them as axioms (Meyer, 2015). Within this lineage, proof orientation means that specifications, implementations, and correctness arguments are expressed in the same mathematical framework. This suggests that POPLs are best understood as a family of language designs that internalize proof obligations, not only a family of type theories.
2. Architectural forms of POPLs
The literature presents several distinct architectures for integrating programs and proofs.
| System or family | Integration mechanism | Distinctive feature |
|---|---|---|
| F* and Verus | Executable code plus formal specifications checked by an SMT-based verifier | Verus uses explicit requires/ensures; F* uses dependent/refinement types |
| GallinaC | Shallow embedding of an imperative language in Gallina/Rocq | program S A, mutable state, pointers, allocation, unbounded while |
| PML 2 | ML-like language where proofs are terminating programs | Curry-style, call-by-value, control operator, subtyping |
| ATS | Separation of statics and dynamics with programming with theorem-proving | Proofs internalize constraint solving and are erased after checking |
SL/SA framework |
Abstract Hoare-style logic with realizability extraction into ST |
Proofs extract mixed functional/imperative stateful programs |
In SMT-assisted POPLs, executable code and formal proof obligations are interleaved in ordinary source files. Verus expresses correctness through explicit preconditions, postconditions, and loop invariants, whereas F* relies more heavily on dependent and refinement types, so code and proof are more tightly intertwined (Jain et al., 1 Aug 2025). In both cases, an SMT solver discharges generated obligations before execution.
Other POPLs emphasize a more direct unification of programming and proving. PML 2 provides “a uniform environment for programming, and for proving properties of programs in an ML-like setting,” with no syntactic distinction between programs and proofs; propositions are types, and proofs are programs that must terminate when used proof-theoretically (Lepigre, 2019). ATS instead enforces a complete separation between statics and dynamics, so that programs do not occur inside types, while still supporting “programming with theorem-proving” through proof terms that solve type-checking constraints and are then erased (Xi, 2017).
Imperative proof-oriented design is explicit in GallinaC, a shallow embedding of a Turing-complete imperative language directly inside Gallina, the language of the Rocq proof assistant. GallinaC is intended for low-level software and Trusted Computing Base components, but it is deliberately hosted inside the proof assistant so that program proofs and tool reasoning remain machine-checked in the same environment (Fort et al., 16 Sep 2025). A related but more abstract route appears in the SL/SA framework, where proofs in a first-order logic with abstract Hoare triples are interpreted as sequential stateful programs via realizability and a state-monad semantics (Powell, 2023).
3. Proof development as a human process
A major theme in the POPL literature is that proof-oriented programming is not only a matter of formal expressiveness; it is also a matter of ergonomics. “How Are Programs Found?” argues that the programs-as-proofs equation is exact at the level of final artifacts but misleading if it is taken as a model of actual human creation. On that account, rigor is indispensable for codification, but intuition, trial and error, and experimentation are indispensable for discovery, and strongly disciplined languages may optimize the former while obstructing the latter (Emerich, 2016).
This concern is borne out empirically by the 2025 telemetry study of expert proof-writing in F* and Verus. The study instrumented VSCode extensions for eight experts, collected more than 18,000 annotated telemetry events, and found that proof development is not a linear pipeline from specification to implementation to proof; specification, implementation, and proof activity are interleaved throughout the session (Jain et al., 1 Aug 2025). In F*, about 55–65% of time went to specification/proof work, 20–40% to implementation, and 10–20% to testing; in Verus, about 60% of time was spent on proof writing. Average verifier invocation rates were 3.39 per minute in F* and 9.11 per minute in Verus. Average active errors were 1.49 in F* and 1.9 in Verus, but some Verus sessions spiked to 35–40 active errors, while stronger performers often stayed around 0–4.
Using -means clustering over behavioral features, the study identified three strategy archetypes: Spec-first Planners, Rapid Verifiers, and Balanced users. In F*, Spec-first Planners had 100% success with the shortest median duration, 21.89 minutes, whereas Rapid Verifiers had 67% success. In Verus, the Spec-first Planner singleton finished successfully in 11.77 minutes, while Rapid Verifiers had 60% success and the longest median duration, 26.10 minutes (Jain et al., 1 Aug 2025). The study also identified informal but predictive practices that final code snapshots conceal: deliberate pauses, partial or high-level specifications, temporary deferral with assume, admit, or comments, lemma reuse, and specification changes when the original proof becomes too hard.
Taken together, these results reinforce the earlier ergonomics argument. POPLs do not merely need expressive proof systems; they need workflows that support movement from vague intent to formalization. This suggests that practical proof orientation depends as much on the organization of discovery as on the strength of the final proof language.
4. Semantics, state, and proof obligations
The technical core of POPLs lies in how they represent proof obligations and program meaning. In F*, proof orientation is often type-directed: a definition is synthesized or checked against a specification encoded as a type, and refinement types express semantic properties such as non-negativity or sortedness. The quicksort example in the F* synthesis work makes this explicit: the type of sort states that the result is sorted and a permutation of the input, and auxiliary lemmas are ordinary F* definitions whose types are propositions (Chakraborty et al., 2024).
In PML 2, equational reasoning is internalized through two dedicated type formers: membership types and restriction types . Equality itself is encoded as . Proofs are terminating programs, but equalities are “exclusively managed by the type-checker,” so a proof typically consists of recursive calls, lemma applications, and pattern matchings rather than explicit rewrite choreography (Lepigre, 2019). The system is Curry-style and call-by-value, supports general recursion and classical control operators, and uses termination checking to protect the proof-relevant fragment.
ATS takes a different route. Its defining principle is a complete separation between statics and dynamics: static terms form types, propositions, and constraints, while dynamic programs are evaluated operationally and do not occur inside types (Xi, 2017). This separation permits practical features such as general recursion, recursive types, and effects, while proof terms are used to internalize constraint solving during type-checking. In the canonical list-append example, a proof relation such as is constructed alongside the resulting indexed list, and proof erasure guarantees that these proof terms have no runtime effect.
Imperative POPLs require an explicit account of mutable state and loops. GallinaC represents programs as Gallina terms of type , with monadic effects for state, failure, and non-termination. Its unbounded while is defined by a fixed-point construction rather than fuel, and the monad uses option, with None representing bottom or non-termination (Fort et al., 16 Sep 2025). The language distinguishes pure expressions from commands, separates compiler-friendly temporaries from mutable store variables, and gives pointers explicit provenance. Proofs are carried out directly in Rocq using a shallow separation logic over states, including predicates , separating conjunction **, separating implication -*, and Hoare-style triples .
A closely related logical perspective appears in the stateful realizability framework of SL and SA, where sequents have Hoare-style preconditions and postconditions, and proofs are extracted into a mixed functional/imperative language ST whose denotation is given by the state-monad shape 0 (Powell, 2023). Here the proof-program correspondence is literally stateful: a proof of a triple produces a term that, when run in a state satisfying the precondition, returns both a witness for the logical content and a new state satisfying the postcondition.
5. Automation, synthesis, and proof reuse
Recent work has treated POPLs as a natural substrate for AI-assisted synthesis because proof-oriented code is already machine-checkable. “Towards Neural Synthesis for SMT-Assisted Proof-Oriented Programming” introduced a corpus of 600K lines of open-source F* programs and proofs, around 32K top-level F* definitions, and a program-fragment checker that re-checks top-level definitions through F*’s interactive JSON API; the extended corpus later grew to 940K lines and 54K top-level definitions (Chakraborty et al., 2024). The study reports that fine-tuned smaller models, such as Phi-2 and StarCoder, compare favorably with much larger models such as GPT-4, and that type-based retrieval augmentation significantly improves verify@k performance.
“Building A Proof-Oriented Programmer That Is 64% Better Than GPT-4o Under Data Scarcity” addresses the low-resource nature of F* directly. It presents PoPilot, a 14B-parameter model trained with synthetic data augmentation for both generation and repair at function and repository level (Zhang et al., 17 Feb 2025). On repository-level evaluation, PoPilot reached Generate@5 = 33.0 and Gen+Rep = 39.4, compared with GPT-4o at 22.2 and 23.9, respectively; the paper summarizes this as a 64% relative margin over GPT-4o in project-level proof-oriented programming. It also reports a 54% relative improvement over GPT-4o’s self-repair when PoPilot repairs GPT-4o outputs. The training pipeline combines synthetic F* tasks, mixed reasoning datasets, repository-context generation, and both synthetic and model-generated repair data.
The expert-process study on F* and Verus translates human proof-writing behavior into explicit design guidance for AI proof assistants: encourage early specification drafting, expose sub-goal decomposition, keep active errors bounded and local, manage verifier interaction in a disciplined way, and support online lemma and documentation retrieval (Jain et al., 1 Aug 2025). Its case study implements a two-agent F* proof system using AutoGen, with a Proof Expert Agent and a Syntax Expert Agent plus GraphRAG retrieval. On T4 and T1, the system produced correct verified solutions in 8 and 7 refinement loops, while a naive o4-mini baseline failed to produce a correct verified solution within 30 verifier refinement loops; the paper interprets this as roughly a 3.75× reduction in verification calls.
Proof artifacts can also be reused beyond synthesis. “Compiling by Proving” turns All-Path Reachability Proofs generated by symbolic execution in K into optimized rewrite rules, so that proofs become a compilation artifact rather than a terminal verification byproduct (Zhao et al., 26 Sep 2025). The implementation compiled 131 out of 149 EVM opcodes, or 87.9% coverage, achieved an average 89.6% reduction in rewriting steps, and reported a geometric-mean concrete-execution speedup of 2.189× and symbolic-execution speedup of 1.442×. At whole-program scope on Rust MIR, symbolic execution time dropped from 2438.26 seconds to 4.668 seconds, about a 522× speedup. This extends proof orientation from verification and synthesis to semantics-based optimization.
6. Significance and unresolved tensions
POPLs are most often justified by high-assurance use cases. The F* synthesis corpus is drawn from real systems and includes software used in production systems “ranging from Windows and Linux to Python and Firefox” (Chakraborty et al., 2024). GallinaC is motivated by low-level imperative software in the Trusted Computing Base, including operating-system kernels, where ordinary imperative languages are said to have “overly permissive” semantics that make proofs tedious and error-prone (Fort et al., 16 Sep 2025). In these settings, POPLs matter because they aim to collapse specification, implementation, and correctness argument into a single auditable artifact.
Several common simplifications are not supported by the literature. POPLs are not restricted to total, purely functional, constructive systems: PML 2 is call-by-value, supports general recursion and a control operator with a classical-logic interpretation; ATS is designed specifically to accommodate recursion, recursive types, and effects; GallinaC is imperative and Turing-complete; and the SL/SA framework extracts imperative stateful programs from proofs (Lepigre, 2019). Nor are POPLs confined to post-hoc verification. The dominant design across these systems is integrated construction, in which the program is written against a formal specification from the start.
At the same time, the literature repeatedly emphasizes trade-offs rather than closure. The ergonomics argument distinguishes discovery from codification and warns that languages that behave like proof assistants too early may hinder exploration (Emerich, 2016). GallinaC explicitly contrasts shallow and deep embedding, noting that MetaCoq reification lies outside Rocq’s proof kernel and is therefore a trust boundary, while final code generation is also outside Rocq though supported by CompCert validation tools (Fort et al., 16 Sep 2025). Rewriting-based equivalence work based on LCTRSs is sound but not complete, relies on heuristics for unification modulo axiomatized symbols, and currently requires user-supplied helper circularities for some loop proofs (Ciobâcă et al., 2020). AI work identifies the low-resource character of proof-oriented code and the scarcity of repository-scale proof data as central bottlenecks (Zhang et al., 17 Feb 2025).
A plausible synthesis is that POPLs are converging not toward a single canonical language, but toward a spectrum of proof-program integration strategies. Some systems emphasize type-theoretic intrinsic proofs, some stateful or Hoare-style reasoning, some shallow embedding inside proof assistants, and some verifier-guided synthesis or proof reuse. The recurring problem is to preserve rigorous codification while making room for planning, decomposition, experimentation, and incremental strengthening. That tension, rather than any one calculus or implementation technique, defines the field’s current research agenda.