{#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 xs = loop 0 n 0 body where body = \i acc -> acc + (xs !! i) n = length xs \end{code}
-
*Function subtyping:* `body` called on `i :: Btwn 0 (llen xs)`
-
Hence, indexing with `!!` is safe.
Demo: Tweak `loop` exit condition?
Example: Summing `Nat`s -----------------------
\begin{code} {-@ listNatSum :: [Nat] -> Nat @-} listNatSum xs = loop 0 n 0 body where body = \i acc -> acc + (xs !! i) n = length xs \end{code}
---- ---- --------------------------------------- (+) `::` `x:Int -> y:Int -> {v:Int| v=x+y}` `<:` `Nat -> Nat -> Nat` ---- ---- ---------------------------------------
Example: Summing `Nat`s ----------------------- \begin{code}
{-@ listNatSum :: [Nat] -> Nat @-} listNatSum xs = loop 0 n 0 body where body = \i acc -> acc + (xs !! i) n = length xs \end{code}
Hence, verified by *instantiating* `α` of `loop` with `Nat`
`Int -> Int -> Nat -> (Int -> Nat -> Nat) -> Nat`
Example: Summing `Nat`s ----------------------- \begin{code}
{-@ listNatSum :: [Nat] -> Nat @-} listNatSum xs = loop 0 n 0 body where body = \i acc -> acc + (xs !! i) n = length xs \end{code}
+ Parameter `α` corresponds to *loop invariant* + Instantiation corresponds to invariant *synthesis* Instantiation And Inference --------------------------- +
Polymorphic instantiation happens *everywhere*
+
Automatic inference is crucial
+
*Cannot use* unification (unlike indexed approaches)
+
*Can reuse* [SMT/predicate abstraction.](http://goto.ucsd.edu/~rjhala/papers/liquid_types.html)
Iteration Dependence -------------------- **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** loop iteration...
-
... cannot instantiate `α` with `{v:Int | v = n + m}`
**Problem:** Need *iteration-dependent* invariants...