{#simplerefinements} ======================= Simple Refinement Types ----------------------- Simple Refinement Types ======================= Types + Predicates ------------------ Example: Integers equal to `0` ------------------------------
\begin{code} {-@ type Zero = {v:Int | v = 0} @-} {-@ zero :: Zero @-} zero = 0 \end{code}
Refinement types via special comments `{-@ ... @-}`
[DEMO](../hs/000_Refinements.hs)
Refinements Are Predicates ========================== From A Decidable Logic ----------------------
1. Expressions 2. Predicates
**Refinement Logic: QF-UFLIA** Quant.-Free. Uninterpreted Functions and Linear Arithmetic
Expressions -----------
\begin{spec}
e := x, y, z,... -- variable | 0, 1, 2,... -- constant | (e + e) -- addition | (e - e) -- subtraction | (c * e) -- linear multiplication | (f e1 ... en) -- uninterpreted function \end{spec} Predicates ----------
\begin{spec}
p := e -- atom | e1 == e2 -- equality | e1 < e2 -- ordering | (p && p) -- and | (p || p) -- or | (not p) -- negation \end{spec}
Refinement Types ----------------
\begin{spec}
b := Int | Bool | ... -- base types | a, b, c -- type variables t := {x:b | p} -- refined base | x:t -> t -- refined function \end{spec} Subtyping Judgment ------------------
$$\boxed{\Gamma \vdash t_1 \preceq t_2}$$

Where **environment** $\Gamma$ is a sequence of binders
$$\Gamma \defeq \overline{\bindx{x_i}{t_i}}$$
Subtyping is Implication ------------------------
$$\boxed{\Gamma \vdash t_1 \preceq t_2}$$
[PVS' Predicate Subtyping](http://pvs.csl.sri.com/papers/subtypes98/tse98.pdf)
(For **Base** Types ...) Subtyping is Implication ------------------------
$$\boxed{\Gamma \vdash t_1 \preceq t_2}$$
$$ \begin{array}{rl} {\mathbf{If\ VC\ is\ Valid}} & \bigwedge_i P_i \Rightarrow Q \Rightarrow R \\ & \\ {\mathbf{Then}} & \overline{\bindx{x_i}{P_i}} \vdash \reft{v}{b}{Q} \subty \reft{v}{b}{R} \\ \end{array} $$ Example: Natural Numbers ------------------------
\begin{spec}
type Nat = {v:Int | 0 <= v} \end{spec}
$$ \begin{array}{rcrccll} \mathbf{VC\ is\ Valid:} & \True & \Rightarrow & v = 0 & \Rightarrow & 0 \leq v & \mbox{(by SMT)} \\ % & & & & & \\ \mathbf{So:} & \emptyset & \vdash & \Zero & \subty & \Nat & \\ \end{array} $$

Hence, we can type: \begin{code} {-@ zero' :: Nat @-} zero' = zero -- zero :: Zero <: Nat \end{code}
Contracts: Function Types ========================= {#as} ------ Pre-Conditions --------------
\begin{code} safeDiv n d = n `div` d -- crashes if d==0 \end{code}
**Requires** non-zero input divisor `d` \begin{code} {-@ type NonZero = {v:Int | v /= 0} @-} \end{code}

Specify pre-condition as **input type** \begin{code} {-@ safeDiv :: n:Int -> d:NonZero -> Int @-} \end{code}
Precondition: `safeDiv` ----------------------- Specify pre-condition as **input type** \begin{spec}
{-@ safeDiv :: n:Int -> d:NonZero -> Int @-} \end{spec}
Precondition is checked at **call-site** \begin{code} {-@ bad :: Nat -> Int @-} bad n = 10 `safeDiv` n \end{code}
**Rejected As** $$\bindx{n}{\Nat} \vdash \reftx{v}{v = n} \not \subty \reftx{v}{v \not = 0}$$
Precondition: `safeDiv` ----------------------- Specify pre-condition as **input type** \begin{spec}
{-@ safeDiv :: n:Int -> d:NonZero -> Int @-} \end{spec}
Precondition is checked at **call-site** \begin{code} {-@ ok :: Nat -> Int @-} ok n = 10 `safeDiv` (n+1) \end{code}
**Verifies As** $\bindx{n}{\Nat} \vdash \reftx{v}{v = n+1} \subty \reftx{v}{v \not = 0}$
Precondition: `safeDiv` ----------------------- Specify pre-condition as **input type** \begin{spec}
{-@ safeDiv :: n:Int -> d:NonZero -> Int @-} \end{spec}
Precondition is checked at **call-site** \begin{spec}
{-@ ok :: Nat -> Int @-} ok n = 10 `safeDiv` (n+1) \end{spec}
**Verifies As** $$(0 \leq n) \Rightarrow (v = n+1) \Rightarrow (v \not = 0)$$ Post-Conditions --------------- **Ensures** output is a `Nat` greater than input `x`. \begin{code} abs x | 0 <= x = x | otherwise = 0 - x \end{code}
Specify post-condition as **output type** \begin{code} {-@ abs :: x:Int -> {v:Nat | x <= v} @-} \end{code}

**Dependent Function Types** Outputs *refer to* inputs
Postcondition: `abs` -------------------- Specify post-condition as **output type** \begin{spec}
{-@ abs :: x:Int -> {v:Nat | x <= v} @-} abs x | 0 <= x = x | otherwise = 0 - x \end{spec}
Postcondition is checked at **return-site**
Postcondition: `abs` -------------------- Specify post-condition as **output type** \begin{spec}
{-@ abs :: x:Int -> {v:Nat | x <= v} @-} abs x | 0 <= x = x | otherwise = 0 - x \end{spec}
**Verified As**
$$\begin{array}{rll} \bindx{x}{\Int},\bindx{\_}{0 \leq x} & \vdash \reftx{v}{v = x} & \subty \reftx{v}{0 \leq v \wedge x \leq v} \\ \bindx{x}{\Int},\bindx{\_}{0 \not \leq x} & \vdash \reftx{v}{v = 0 - x} & \subty \reftx{v}{0 \leq v \wedge x \leq v} \\ \end{array}$$ Postcondition: `abs` -------------------- Specify post-condition as **output type** \begin{spec}
{-@ abs :: x:Int -> {v:Nat | x <= v} @-} abs x | 0 <= x = x | otherwise = 0 - x \end{spec}
**Verified As**
$$\begin{array}{rll} (0 \leq x) & \Rightarrow (v = x) & \Rightarrow (0 \leq v \wedge x \leq v) \\ (0 \not \leq x) & \Rightarrow (v = 0 - x) & \Rightarrow (0 \leq v \wedge x \leq v) \\ \end{array}$$ Recipe Scales Up ----------------
Define type *checker* and get *inference* for free [[PLDI 08]](http://goto.ucsd.edu/~rjhala/papers/liquid_types.pdf)

Scales to Collections, HOFs, Polymorphism ...

[DEMO](../hs/001_Refinements.hs)
[[continue...]](02_Measures.lhs.slides.html)