{#measures} ============ Measuring Data Types -------------------- Measuring Data Types ==================== Recap ----- 1.
**Refinements:** Types + Predicates
2.
**Subtyping:** SMT Implication
Example: Length of a List ------------------------- Given a type for lists:
\begin{code} data L a = N | C a (L a) \end{code}

We can define the **length** as:
\begin{code} {-@ measure llen :: (L a) -> Int llen (N) = 0 llen (C x xs) = 1 + (llen xs) @-} \end{code} Example: Length of a List ------------------------- \begin{spec} {-@ measure llen :: (L a) -> Int llen (N) = 0 llen (C x xs) = 1 + llen xs @-} \end{spec}
We **strengthen** data constructor types
\begin{spec}
data L a where N :: {v: L a | (llen v) = 0} C :: a -> t:_ -> {v:_| llen v = 1 + llen t} \end{spec} Measures Are Uninterpreted -------------------------- \begin{spec}
data L a where N :: {v: L a | (llen v) = 0} C :: a -> t:_ -> {v:_| llen v = 1 + llen t} \end{spec}
`llen` is an **uninterpreted function** in SMT logic Measures Are Uninterpreted --------------------------
In SMT, [uninterpreted function](http://fm.csl.sri.com/SSFT12/smt-euf-arithmetic.pdf) $f$ obeys **congruence** axiom:
$$\forall \overline{x}, \overline{y}. \overline{x} = \overline{y} \Rightarrow f(\overline{x}) = f(\overline{y})$$
Other properties of `llen` asserted when typing **fold** & **unfold**

Crucial for *efficient*, *decidable* and *predictable* verification.
Measures Are Uninterpreted -------------------------- Other properties of `llen` asserted when typing **fold** & **unfold**
\begin{spec}**Fold**
z = C x y -- z :: {v | llen v = 1 + llen y} \end{spec}

\begin{spec}**Unfold**
case z of N -> e1 -- z :: {v | llen v = 0} C x y -> e2 -- z :: {v | llen v = 1 + llen y} \end{spec}
Measured Refinements -------------------- Now, we can verify:
\begin{code} {-@ length :: xs:L a -> EqLen xs @-} length N = 0 length (C _ xs) = 1 + length xs \end{code}

Where `EqLen` is a type alias: \begin{code} {-@ type EqLen Xs = {v:Nat | v = llen Xs} @-} \end{code}
List Indexing Redux ------------------- We can type list lookup: \begin{code} {-@ (!) :: xs:L a -> LtLen xs -> a @-} (C x _) ! 0 = x (C _ xs) ! i = xs ! (i - 1) _ ! _ = liquidError "never happens!" \end{code}
Where `LtLen` is a type alias: \begin{code} {-@ type LtLen Xs = {v:Nat | v < llen Xs} @-} \end{code}
Demo:   What if we *remove* the precondition?
Multiple Measures -----------------
**Multiple** measures by **conjoining** refinements.
e.g. Red Black Tree + Height + Color + Nodes, etc.
Refined Data Constructors ========================= {#refined-data-cons} --------------------- Can encode *other* invariants **inside constructors**

\begin{code} {-@ data L a = N | C { x :: a , xs :: L {v:a| x <= v} } @-} \end{code}

Head `x` is less than **every** element of tail `xs`

i.e. specifies **increasing** Lists
Increasing Lists ---------------- \begin{spec}
data L a where N :: L a C :: x:a -> xs: L {v:a | x <= v} -> L a \end{spec}
-
We **check** property when **folding** `C`
-
We **assume** property when **unfolding** `C`
Increasing Lists ---------------- Demo: Insertion Sort (hover for inferred types)
\begin{code} insertSort xs = foldr insert N xs insert y (x `C` xs) | y <= x = y `C` (x `C` xs) | otherwise = x `C` insert y xs insert y N = y `C` N \end{code}
Recap -----

1. Refinements: Types + Predicates 2. Subtyping: SMT Implication 3. **Measures:** Strengthened Constructors
Logic + Analysis for Collections