Abstract Refinements {#induction} ================================= Decoupling Invariants & Code ----------------------------
Abstract refinements decouple invariants from code
**Next:** Precise Specifications for HOFs Structural Induction ==================== Example: Lists --------------
\begin{code} data L a = N | C a (L a) \end{code}
Lets write a generic loop over lists ...
Example: `foldr` ----------------

\begin{code} foldr :: (α -> β -> β) -> β -> L α -> β foldr f acc N = acc foldr f acc (C x xs) = f x (foldr f acc xs) \end{code} Problem ------- Recall our *failed attempt* to write `append` with `foldr`
\begin{spec} {-@ app :: xs:_ -> ys:_ -> UnElems xs ys @-} app xs ys = foldr C ys xs \end{spec}
- Property holds after *last* iteration - Cannot instantiate `α` with `UnElems xs ys`
Problem ------- Recall our *failed attempt* to write `append` with `foldr`
\begin{spec} {-@ app :: xs:_ -> ys:_ -> UnElems xs ys @-} app xs ys = foldr C ys xs \end{spec}
Need to **relate** each *iteration* with *accumulator* `acc` Solution: Inductive `foldr` ---------------------------

Lets brace ourselves for the type...
Solution: Inductive `foldr` --------------------------- \begin{code} {-@ ifoldr :: forall a b

b -> Prop>. (xs:_ -> x:_ -> b

-> b) -> b

-> ys:L a -> b

@-} ifoldr f b N = b ifoldr f b (C x xs) = f xs x (ifoldr f b xs) \end{code}

Lets step through the type...
`ifoldr`: Abstract Refinement ----------------------------- \begin{spec}
p :: L a -> b -> Prop step :: xs:_ -> x:_ -> b

-> b base :: b

ys :: L a out :: b

\end{spec}
`(p xs b)` relates `b` with **folded** `xs` `p :: L a -> b -> Prop` `ifoldr`: Base Case ------------------- \begin{spec}

p :: L a -> b -> Prop step :: xs:_ -> x:_ -> b

-> b base :: b

ys :: L a out :: b

\end{spec}
`base` is related to **empty** list `N` `base :: b

` `ifoldr`: Ind. Step ------------------- \begin{spec}

p :: L a -> b -> Prop step :: xs:_ -> x:_ -> b

-> b base :: b

ys :: L a out :: b

\end{spec}
`step` **extends** relation from `xs` to `C x xs` `step :: xs:_ -> x:_ -> b

-> b

` `ifoldr`: Output ---------------- \begin{spec}

p :: L a -> b -> Prop step :: xs:_ -> x:_ -> b

-> b base :: b

ys :: L a out :: b

\end{spec}
Hence, relation holds between `out` and **entire input** list `ys` `out :: b

` Using `ifoldr`: Size ------------------- We can now verify
\begin{code} {-@ size :: xs:_ -> {v:Int| v = size xs} @-} size = ifoldr (\_ _ n -> n + 1) 0 \end{code}

by *automatically instantiating* `p` with `\xs acc -> acc = size xs`
Using `foldr`: Append --------------------- We can now verify
\begin{code} {-@ (++) :: xs:_ -> ys:_ -> UnElems xs ys @-} xs ++ ys = ifoldr (\_ -> C) ys xs \end{code}

By *automatically* instantiating `p` with `\xs acc -> elems acc = Set_cup (elems xs) (elems ys)`
More Examples ------------- Induction over *structures* from `GHC.List`
+ `length` + `append` + `filter` + ...
[DEMO 02_AbstractRefinements.hs #2](../hs/02_AbstractRefinements.hs) Recap -----
Abstract refinements *decouple* **invariant** from **iteration**
**Precise** specs for higher-order functions.

**Automatic** checking and instantiation by SMT.
Recap ----- 1. Refinements: Types + Predicates 2. Subtyping: SMT Implication 3. Measures: Strengthened Constructors 4. Abstract: Refinements over Type Signatures +
**Functions**
+
**Recursive Data** [continue]
5.
[Evaluation](11_Evaluation.lhs.slides.html)