---
title: 'ListFold: Verified Left-Fold in OCaml'
url: https://www.emergentmind.com/topics/listfold
type: topic
---

# ListFold: Verified Left-Fold in OCaml

ListFold is the canonical left-fold operation on lists, fundamental in functional and higher-order programming. In the context of formal verification, especially as articulated by the "Unfolding Iterators" methodology, ListFold is specified, implemented, and deductively verified using OCaml in combination with the Gospel specification language and the Cameleer verification framework. This approach enables modular and rigorous reasoning about higher-order iteration schemas, ensuring that classic iterators such as left-fold are correct with respect to precise logical specifications [2506.20310].

## 1. Specification of ListFold via the Gospel Contract

The specification of ListFold is formalized through Gospel, a behavioral specification language designed for OCaml. The ListFold function assumes the type signature:

```
val list_fold : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
```

The Gospel contract uses the `folds` clause, introducing two key predicates:

- **permitted**: Enforces that the sequence of visited elements is a prefix of the input list, i.e., for all $v$, $\text{length}(v) \leq \text{length}(xs)$ and $\forall i,\ 0 \leq i < \text{length}(v) \implies \text{nth}(xs, i) = \text{nth}(v, i)$.
- **complete**: Specifies completeness once all elements have been visited, i.e., $\text{length}(v) = \text{length}(xs)$.

There is no further `requires` clause; totality is assumed for all lists. The use of `folds` instructs the toolchain to synthesize a first-order cursor-loop matching functional recursion over the list structure [2506.20310].

## 2. OCaml Implementation and Invariants

A direct recursive implementation of ListFold adheres to standard functional programming idioms, with explicit Gospel annotations specifying termination and correctness invariants. The implementation is:

```ocaml
let rec list_fold (f : 'a -> 'b -> 'a) (init : 'a) (xs : 'b list) : 'a =
  match xs with
  | []       -> init
  | x :: xs' ->
      (*@
        variant length xs
        invariant
          forall v.
            exists ys. xs = v @ ys /\
            acc = fold_left f init v
      *@)
      list_fold f (f init x) xs'
```

- The `variant length xs` guarantees termination by ensuring each recursive call operates on a shorter list.
- The **ghost invariant** ensures that at every recursion point, the accumulator matches the left-fold of the function over the currently processed prefix of `xs`. That is, for every prefix $v$ and residual $ys$ such that $xs = v~@~ys$, the accumulator satisfies $acc = fold\_left~f~init~v$ [2506.20310].

## 3. Equational Characterization and Correctness

The correctness theorem for ListFold, as produced by Why3 from the specification and implementation, states that the list_fold function coincides with the standard equational definition of left-fold:

\[
\forall f : A \to B \to A,\, \forall init : A,\, \forall xs : B~\mathrm{list},\;
  list\_fold~f~init~xs =
  fold\_left~f~init~xs
\]

with the inductive unfolding:

\[
\begin{array}{l}
fold\_left~f~init~[] = init \\
fold\_left~f~init~(x::xs) = fold\_left~f~(f~init~x)~xs
\end{array}
\]

For specific $f$ and $init$ (e.g., \(f = (a, x) \mapsto a + x\), $init = 0$), this recovers familiar computations such as sums over lists [2506.20310].

## 4. Verification Conditions and Proof Methodology

Deductive verification within Cameleer—via the Gospel→WhyML→Why3 pipeline—produces a finite set of verification conditions (VCs):

1. **Termination VC**: Proves that $\text{length}(xs') < \text{length}(xs)$ at each recursive call.
2. **Precondition VC**: Validates the ghost invariant at function entry; trivially satisfied ($v=[]$, $acc=init$).
3. **Invariant-Preservation VC**: Shows the invariant's inductive step holds at each recursive call.
4. **Postcondition VC**: At the base case ($xs=[]$), confirms $init = fold\_left~f~init~[]$.

Key to discharging these VCs is the existential invariant $\exists v, ys.\; xs = v @ ys \land acc = fold\_left(f, init, v)$. The proof steps involve pattern-matching inversion, instantiating existential witnesses ($v' = v @ [x]$), and utilizing Why3’s list-library lemmas. Proofs for arithmetic and simple list equalities are resolved automatically by the SMT solver Alt-Ergo [2506.20310].

## 5. Modularity and Ghost State Techniques

The methodology hinges on two crucial ideas:

- **Ghost state**: Tracking the processed prefix of $xs$ via an existential variable $v$ ensures accurate reasoning about functional state across iterations.
- **permitted/complete abstraction**: These Gospel contract components modularize the iteration schema, describing the expected access pattern over the data structure and when computations are complete.

Once ListFold is verified, correctness results transfer to any client instantiating the fold pattern (e.g., sum, map, filter), as all such instantiations reuse the same loop skeleton and VCs. This modularity is key for deductive verification of higher-order iterators [2506.20310].

## 6. High-Level Proof Strategy and Challenges

The overarching strategy initiates from a high-level Gospel contract, automatically translates it to a WhyML function skeleton (using explicit recursion and ghost state), and generates Why3 VCs corresponding to termination, invariant preservation, and correctness. The loop invariant and permitted/complete predicates enable reduction of the higher-order verification task to standard first-order recursive reasoning.

A primary challenge in verifying higher-order iterators is universal quantification over function arguments. By "unfolding" the iteration into an explicit cursor-based recursion, the verification reduces to proof of classic loop invariants. The infrastructure provided by Cameleer, Gospel, and automated solvers makes such proofs tractable in practice, with little manual intervention given suitable contracts and invariants [2506.20310].

Source: https://www.emergentmind.com/topics/listfold