Total functional programming
Total functional programming is a programming paradigm that restricts the range of programs to those that are provably terminating.
Restrictions
Termination is guaranteed by the following restrictions:- A restricted form of recursion, which operates only upon 'reduced' forms of its arguments, such as Walther recursion, substructural recursion, or "strongly normalizing" as proven by abstract interpretation of code.
- Every function must be a total function. That is, it must have a definition for everything inside its domain.
- * There are several possible ways to extend commonly used partial functions such as division to be total: choosing an arbitrary result for inputs on which the function is normally undefined ; adding another argument to specify the result for those inputs; or excluding them by use of type system features such as refinement types.
For example, quicksort is not trivially shown to be substructural recursive, but it only recurs to a maximum depth of the length of the vector. A quicksort implementation on lists is, using Haskell:
import Data.List
qsort =
qsort =
qsort = let = partition as
in qsort lesser ++ ++ qsort greater
To make it substructural recursive using the length of the vector as a limit, we could do:
import Data.List
qsort x = qsortSub x x
-- minimum case
qsortSub as = as -- shows termination
-- standard qsort cases
qsortSub = -- nonrecursive, so accepted
qsortSub = -- nonrecursive, so accepted
qsortSub = let = partition as
-- recursive, but recurs on ls, which is a substructure of
-- its first input.
in qsortSub ls lesser ++ ++ qsortSub ls greater
Some classes of algorithms have no theoretical upper bound but do have a practical upper bound.
Another outcome of total functional programming is that both strict evaluation and lazy evaluation result in the same behaviour, in principle; however, one or the other may still be preferable for performance reasons.
In total functional programming, a distinction is made between data and codata—the former is finitary, while the latter is potentially infinite. Such potentially infinite data structures are used for applications such as I/O. Using codata entails the usage of such operations as corecursion. However, it is possible to do I/O in a total functional programming language also without codata.
Both Epigram and Charity could be considered total functional programming languages, even though they do not work in the way Turner specifies in his paper. So could programming directly in plain System F, in Martin-Löf type theory or the Calculus of Constructions.