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

Very 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}
LiquidHaskell infers `f` called with values `(Btwn lo hi)` Example: Summing Lists ---------------------- \begin{code} listSum :: [Int] -> Int listSum xs = loop 0 n 0 body where body = \i acc -> acc + (xs !! i) n = length xs \end{code}
**Function Subtyping** + `body` called with `i :: Btwn 0 (llen xs)` + Hence, indexing with `!!` is safe.
Demo: Tweak `loop` exit condition?
Polymorphic Instantiation ========================= {#poly} -------- Example: Summing `Nat`s ----------------------- \begin{code} {-@ sumNats :: [Nat] -> Nat @-} sumNats xs = foldl (+) 0 xs \end{code}
\begin{code} Recall foldl :: (α -> β -> α) -> α -> [β] -> α \end{code}

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

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

`α` is **loop invariant**, instantiation is invariant **synthesis**
Instantiation And Inference --------------------------- Polymorphic instantiation happens *everywhere*...
... so *automatic inference* is crucial
Cannot use *unification* (unlike indexed approaches)
LiquidHaskell uses [SMT and Abstract Interpretation.](http://goto.ucsd.edu/~rjhala/papers/liquid_types.html) 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 `α := {v:Int | v = n + m}`

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