Structure of this book

This book is a work in progress

The first four parts of this book explain the main features of the language using a variety of examples. You should read them sequentially, following along with the associated code samples and exercises. These first four parts are arranged in increasing order of complexity—you can stop after any of them and have a working knowledge of useful fragments of F*.

The remaining parts of the book are more loosely connected and either provide a reference guide to the compiler and libraries, or develop case studies that the reader can choose depending on their interest. Of course, some of those case studies come with prerequisites, e.g., you must have read about effects before tackling the case study on parsers and formatters.

  • Part 1: Basic Functional Programming and Proofs

The first part of this book provides a basic introduction to programming with pure total functions, refinement types, and SMT-based proofs, and how to compile and execute your first F* program. This part of the book revises a previous online tutorial on F* and is targeted at an audience familiar with programming, though with no background in formal proofs. Even if you are familiar with program proofs and dependent types, it will be useful to quickly go through this part, since some elements are quite specific to F*.

  • Part 2: Inductive Types for Data, Proofs, and Computations

We turn next to inductive type definitions, the main mechanism by which a user can define new data types. F*’s indexed inductive types allow one to capture useful properties of data structures, and dependently types functions over these indexed types can be proven to respect several kinds of invariants. Beyond their use for data structures, inductive data types are used at the core of F*’s logic to model fundamental notions like equality and termination proofs, and can also be used to model and embed other programming paradigms within F*.

  • Part 3: Modularity with Interfaces and Typeclasses

We discuss two main abstraction techniques, useful in structuring larger developments: interfaces and typeclasses. Interfaces are a simple information hiding mechanism built in to F*’s module system. Typeclasses are suitable for more advanced developments, providing more flexible abstraction patterns coupled with custom type inference.

  • Part 4: Computational Effects

We introduce F*’s effect system, starting with its primitive effects for total, ghost, and divergent computations. We also provide a brief primer on Floyd-Hoare logic and weakest precondition calculi, connecting them to Dijkstra monads, a core concept in the design of F*’s effect system.

  • Part 5: Tactics and Metaprogramming

We introduce Meta-F*, the metaprogramming system included in F*. Meta-F* can be used to automate the construction of proofs as well as programmatically construct fragments of F* programs. There’s a lot to cover here—the material so far presents the basics of how to get started with using Meta-F* to target specific assertions in your program and to have their proofs be solved using a mixture of tactics and SMT solving.

  • Under the hood: F* & SMT

In this part of the book, we cover how F* uses the Z3 SMT solver. We present a brief overview of F*’s SMT encoding paying attention in particular to F* use of fuel to throttle SMT solver’s unfolding of recursive functions and inductive type definitions. We also cover a bit of how quantifier instantiation works, how to profile Z3’s quantifier instantiation, and some strategies for how to control proofs that are too slow because of excessive quantifier instantiation.

  • Planned content

The rest of the book is still in the works, but the planned content is the following:

  • Part 4: User-defined Effects

    • State

    • Exceptions

    • Concurrency

    • Algebraic Effects

  • Part 5: Tactics and Metaprogramming

    • Reflecting on syntax

    • Holes and proof states

    • Builtin tactics

    • Derived tactics

    • Interactive proofs

    • Custom decision procedures

    • Proofs by reflection

    • Synthesizing programs

    • Tactics for program extraction

  • Part 6: F* Libraries

  • Part 7: A User’s Guide to Structuring and Maintaining F* Developments

    • The Build System

      – Dependence Analysis – Checked files – Sample project

    • Using the F* editor

    • Proofs by normalization
      • Normalization steps

      • Call-by-name vs. call-by-value

      • Native execution and plugins

    • Proof Engineering
      • Building, maintaining and debugging stable proofs

    • Extraction
      • OCaml

      • F#

      • KaRaMeL

      • Partial evaluation

    • Command line options

    • A guide to various F* error messages

    • Syntax guide

    • FAQ

  • Part 8: Steel: A Concurrent Separation Logic Embedded in F*

  • Part 9: Application to High-assurance Cryptography

  • Part 10: Application to Parsers and Formatters