{#simplerefinements} ======================= Simple Refinement Types ----------------------- Simple Refinement Types ======================= Types + Predicates ------------------ Ex: `Int`egers equal to `0` ---------------------------
\begin{code} {-@ type EqZero = {v:Int | v = 0} @-} {-@ zero :: EqZero @-} zero = 0 \end{code}
Refinement types via special comments `{-@ ... @-}`
Demo
Refinements Are Predicates ========================== From A Decidable Logic ---------------------- 1. Expressions 2. Predicates Expressions -----------
\begin{code}
e := x, y, z,... -- variable | 0, 1, 2,... -- constant | (e + e) -- addition | (e - e) -- subtraction | (c * e) -- linear multiplication | (v e1 e2 ... en) -- uninterpreted function \end{code} Predicates ----------
\begin{code}
p := e -- atom | e1 == e2 -- equality | e1 < e2 -- ordering | (p && p) -- and | (p || p) -- or | (not p) -- negation \end{code} Subtyping is Implication ------------------------ [PVS' Predicate Subtyping](http://pvs.csl.sri.com/papers/subtypes98/tse98.pdf) Subtyping is Implication ------------------------

--------- ------------ -------------------------- **If:** `P` `=> Q` **Then:** `{v:t | P}` `<: {v:t | Q}` --------- ------------ -------------------------- Example: Natural Numbers ------------------------ \begin{code}
type Nat = {v:Int | 0 <= v} \end{code}
------------- --------- ---------------- **By SMT:** `v = 0` `=>` `0 <= v` **So:** `EqZero` `<:` `Nat` ------------- --------- ----------------

Hence, we can type: \begin{code} {-@ zero' :: Nat @-} zero' = zero -- zero :: EqZero <: Nat \end{code}
{#universalinvariants} ======================= Types = Universal Invariants ---------------------------- (Notoriously hard with *pure* SMT) Types Yield Universal Invariants ================================ Example: Lists -------------- \begin{code} data L a = N | C a (L a) \end{code}
*Every element* in `nats` is non-negative:
\begin{code} {-@ nats :: L Nat @-} nats = 0 `C` 1 `C` 3 `C` N \end{code}

Demo: What if `nats` contained `-2`?
Example: Even/Odd Lists ----------------------- \begin{code} {-@ type Even = {v:Int | v mod 2 = 0} @-} {-@ type Odd = {v:Int | v mod 2 /= 0} @-} \end{code}
\begin{code} {-@ evens :: L Even @-} evens = 0 `C` 2 `C` 4 `C` N {-@ odds :: L Odd @-} odds = 1 `C` 3 `C` 5 `C` N \end{code}

Demo: What if `evens` contained `1`?
Contracts: Function Types ========================= {#as} ------ Example: `safeDiv` ------------------
**Precondition** divisor is *non-zero*.
\begin{code} {-@ type NonZero = {v:Int | v /= 0} @-} \end{code}
Example: `safeDiv` ------------------
+ **Pre-condition** divisor is *non-zero*. + **Input type** specifies *pre-condition*
\begin{code} {-@ safeDiv :: Int -> NonZero -> Int @-} safeDiv x y = x `div` y \end{code}
Demo: What if precondition does not hold?
Example: `abs` --------------
+ **Postcondition** result is non-negative + **Output type** specifies *post-condition*
\begin{code} {-@ abs :: x:Int -> Nat @-} abs x | 0 <= x = x | otherwise = 0 - x \end{code} {#dependentfunctions} ====================== Dependent Function Types ------------------------
Outputs **refer to** inputs
**Relational** invariants Dependent Function Types ======================== Example: `range` ---------------- `(range i j)` returns `Int`s **between** `i` and `j` Example: `range` ---------------- `(range i j)` returns `Int`s **between** `i` and `j`
\begin{code} {-@ type Btwn I J = {v:_ | (I<=v && v \begin{code} {-@ range :: i:Int -> j:Int -> L (Btwn i j) @-} range i j = go i where go n | n < j = n `C` go (n + 1) | otherwise = N \end{code}
**Note:** Type of `go` is automatically inferred
Example: Indexing Into List --------------------------- \begin{code} (!) :: L a -> Int -> a (C x _) ! 0 = x (C _ xs) ! i = xs ! (i - 1) _ ! _ = liquidError "Oops!" \end{code}
(Mouseover to view type of `liquidError`)

To ensure safety, *require* `i` between `0` and list **length**

Need way to **measure** the length of a list [[continue...]](02_Measures.lhs.slides.html)