A different place to put the specification
The previous lesson wrote a program, wrote a specification alongside it, and proved they agree. There is a second approach that removes the gap by construction.
Rather than checking a program against a separate spec, encode the specification in the type, so strongly that no incorrect program can be given that type. Correctness then follows from type checking, which every compiler already does.
The familiar version of this idea is already in ordinary languages. A function typed as taking an integer cannot be handed a string, and no proof is needed because the program does not compile. The type made a class of errors unwritable rather than detectable.
The question is how far that goes. Ordinary type systems catch shape errors and stop well short of behaviour: nothing in List -> Int says the result is the list's length rather than its first element or 42.
What follows is the machinery for pushing that boundary until the type says exactly what the function must do.

