Termination {#termination}
==========================
\begin{code}
module Termination where
import Prelude hiding (gcd, mod, map)
fib :: Int -> Int
gcd :: Int -> Int -> Int
infixr `C`
data L a = N | C a (L a)
{-@ invariant {v: (L a) | 0 <= (llen v)} @-}
mod :: Int -> Int -> Int
mod a b | a - b > b = mod (a - b) b
| a - b < b = a - b
| a - b == b = 0
merge :: Ord a => L a -> L a -> L a
\end{code}
Dependent != Refinement
-----------------------
**Dependent Types**
+ *Arbitrary terms* appear inside types
+ Termination ensures well-defined
**Refinement Types**
+ *Restricted refinements* appear in types
+ Termination *not* required ...
+ ... except, alas, with *lazy* evaluation!
Refinements & Termination
----------------------------
Fortunately, we can ensure termination *using refinements*
Main Idea
---------
Recursive calls must be on *smaller* inputs
+ [Turing](http://classes.soe.ucsc.edu/cmps210/Winter11/Papers/turing-1936.pdf)
+ [Sized Types](http://dl.acm.org/citation.cfm?id=240882)
Recur On *Smaller* `Nat`
------------------------
**To ensure termination of**
\begin{code}
foo :: Nat -> T
foo x = body
\end{code}
**Check `body` Under Assumption**
`foo :: {v:Nat | v < x} -> T`
*i.e.* require recursive calls have inputs *smaller* than `x`
Ex: Recur On *Smaller* `Nat`
----------------------------
\begin{code}
{-@ fib :: Nat -> Nat @-}
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
\end{code}
Terminates, as both `n-1` and `n-2` are `< n`
Demo:What if we drop the `fib 1` case?
Refinements Are Essential!
--------------------------
\begin{code}
{-@ gcd :: a:Nat -> {b:Nat | b < a} -> Int @-}
gcd a 0 = a
gcd a b = gcd b (a `mod` b)
\end{code}
Need refinements to prove `(a mod b) < b` at *recursive* call!
\begin{code}
{-@ mod :: a:Nat
-> b:{v:Nat|(0 < v && v < a)}
-> {v:Nat| v < b} @-}
\end{code}
Recur On *Smaller* Inputs
-------------------------
What of input types other than `Nat` ?
\begin{code}
foo :: S -> T
foo x = body
\end{code}
**Reduce** to `Nat` case...
Recur On *Smaller* Inputs
-------------------------
What of input types other than `Nat` ?
\begin{code}
foo :: S -> T
foo x = body
\end{code}
Specify a **default measure** `mS :: S -> Int`
**Check `body` Under Assumption**
`foo :: {v:s | 0 <= (mS v) < (mS x)} -> T`
Ex: Recur on *smaller* `List`
-----------------------------
\begin{code}
map f N = N
map f (C x xs) = (f x) `C` (map f xs)
\end{code}
Terminates using **default** measure `llen`
\begin{code}
{-@ data L [llen] a = N
| C (x::a) (xs :: L a) @-}
{-@ measure llen :: L a -> Int
llen (N) = 0
llen (C x xs) = 1 + (llen xs) @-}
\end{code}
Recur On *Smaller* Inputs
-------------------------
What of *smallness* spread across inputs?
\begin{code}
merge xs@(x `C` xs') ys@(y `C` ys')
| x < y = x `C` merge xs' ys
| otherwise = y `C` merge xs ys'
\end{code}
Neither input decreases, but their *sum* does.
Recur On *Smaller* Inputs
-------------------------
Neither input decreases, but their *sum* does.
\begin{code}
{-@ merge :: Ord a => xs:_ -> ys:_ -> _
/ [(llen xs) + (llen ys)] @-}
\end{code}
Synthesize *ghost* parameter equal to `[...]`
Reduces to single-parameter-decrease case.
Important Extensions
--------------------
- Mutual recursion
- Lexicographic ordering...
Recap
-----
Main idea: Recursive calls on *smaller inputs*
- Use refinements to *check* smaller
- Use refinements to *establish* smaller
A Curious Circularity
---------------------
Refinements require termination ...
... Termination requires refinements!
(Meta-theory is tricky, but all ends well.)
Recap
-----
1. **Refinements:** Types + Predicates
2. **Subtyping:** SMT Implication
3. **Measures:** Strengthened Constructors
4. **Abstract Refinements:* Decouple Invariants
5. **Lazy Evaluation:** Requires Termination
6. **Termination:** Via Refinements!
7. **Evaluation**