{#hofs} ========= Higher-Order Functions ---------------------- Types scale to *Higher-Order Functions*
+ map + fold + visitors + callbacks + ...

Difficult with *first-order program logics*
Higher Order Specifications =========================== Example: Higher Order Loop --------------------------
\begin{code} loop :: Int -> Int -> α -> (Int -> α -> α) -> α loop lo hi base f = go lo base where go i acc | i < hi = go (i+1) (f i acc) | otherwise = acc \end{code}
By subtyping, we infer `f` called with values `(Btwn lo hi)` Example: Summing Lists ---------------------- \begin{code} listSum xs = loop 0 n 0 body where body i acc = acc + (xs !! i) n = length xs \end{code}
**Function Subtyping** \begin{spec} loop :: l -> h -> α -> (Btwn l h -> α -> α) -> α \end{spec}

At callsite, since `l := 0` and `h := llen xs` \begin{spec} body :: Btwn 0 (llen xs) -> Int -> Int \end{spec}
Example: Summing Lists ---------------------- \begin{spec} listSum xs = loop 0 n 0 body where body i acc = acc + (xs !! i) n = length xs \end{spec}
**Function Subtyping** \begin{spec} body :: Btwn 0 (llen xs) -> Int -> Int \end{spec}
So `i` is `Btwn 0 (llen xs)`; indexing `!!` is verified safe. {#polyinst} ============ Polymorphic Instantiation -------------------------


"Plugging in" summaries at call-sites
Polymorphic Instantiation ========================= {#poly} -------- Example: Summing `Nat`s ----------------------- \begin{code} {-@ sumNats :: [Nat] -> Nat @-} sumNats xs = foldl (+) 0 xs \end{code}
\begin{spec} Recall foldl :: (α -> β -> α) -> α -> [β] -> α \end{spec}

How to **instantiate** `α` and `β` ?
Function Subtyping ------------------ \begin{spec}
(+) :: x:Int -> y:Int -> {v:Int|v=x+y} <: Nat -> Nat -> Nat \end{spec}
Because, \begin{spec}
|- Nat <: Int -- Contra (in) x:Nat, y:Nat |- {v = x+y} <: Nat -- Co (out) \end{spec}

Because, \begin{spec}
0<=x && 0<=y && v = x+y => 0 <= v \end{spec}
Example: Summing `Nat`s ----------------------- \begin{spec}
{-@ sumNats :: [Nat] -> Nat @-} sumNats xs = foldl (+) 0 xs \end{spec}
\begin{spec} Where: foldl :: (α -> β -> α) -> α -> [β] -> α (+) :: Nat -> Nat -> Nat \end{spec}
Hence, `sumNats` verified by **instantiating** `α,β := Nat`

`α` is **loop invariant**, instantiation is invariant **inference**
Instantiation And Inference --------------------------- Polymorphism ubiquitous, so inference is critical!
**Step 1. Templates** Instantiate with unknown refinements $$ \begin{array}{rcl} \alpha & \defeq & \reft{v}{\Int}{\kvar{\alpha}}\\ \beta & \defeq & \reft{v}{\Int}{\kvar{\beta}}\\ \end{array} $$

**Step 2. Horn-Constraints** By type checking the templates

**Step 3. Fixpoint** Abstract interpretation to get solution for $\kvar{}$
Iteration Dependence -------------------- **Problem:** Cannot use parametric polymorphism to verify
\begin{code} {-@ add :: n:Nat -> m:Nat -> {v:Nat|v=m+n} @-} add n m = loop 0 m n (\_ i -> i + 1) \end{code}
As property only holds after **last iteration** ...
... cannot instantiate $\alpha \defeq \reft{v}{\Int}{v = n + m}$

**Problem:** *Iteration-dependent* invariants...?     [[Continue]](04_AbstractRefinements.lhs.slides.html)