{#simplerefinements} ======================= Simple Refinement Types ----------------------- Simple Refinement Types ======================= Types + Predicates ------------------ Example ------- Integers equal to `0`
\begin{code} {-@ type EqZero = {v:Int | v = 0} @-} \end{code} Example ------- Integers equal to `0`
\begin{code} {-@ zero :: EqZero @-} zero = 0 \end{code}
Refinement types via special comments `{-@ ... @-}`

Demo Lets take a look.
{#refinementsArePredicates} ============================ Refinements Are Predicates -------------------------- Refinements Are Predicates ========================== Subtyping is Implication ------------------------ [Predicate Subtyping](http://pvs.csl.sri.com/papers/subtypes98/tse98.pdf) Subtyping is Implication ------------------------
-------- --- --------------------------------------------- **If** : Refinement of `S` *implies* refinement of `T` **Then** : `S` is a *subtype* of `T` -------- --- ---------------------------------------------
Subtyping is Implication ------------------------
-------- --- ---------------------------- **If** : `p => q` **Then** : `{v : t | p} <: {v : t | q}` -------- --- ---------------------------- Subtyping is Implication ------------------------
-------- --- --------------------------------------------------- **As** : `v=0` *implies* `0<=v` ... via SMT **So** : `{v:Int | v=0} <: {v:Int | 0<=v}` -------- --- --------------------------------------------------- Example: Natural Numbers ------------------------ \begin{code} . type Nat = {v : Int | 0 <= v} \end{code}
Via SMT, LiquidHaskell infers `EqZero <: Nat`, hence:
\begin{code} {-@ zero' :: Nat @-} zero' = zero \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`?
{#functiontypes} ================= Contracts = Function Types -------------------------- Contracts: Function Types ========================= 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 < J)} @-} \end{code} Example: `range` ---------------- `(range i j)` returns `Int`s between `i` and `j`
\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}
**Question:** What is the type of `go` ?
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`)

-
**Q:** How to ensure safety?
-
**A:** Precondition: `i` between `0` and list **length**.
Need way to [measure](#measures) *length of a list* ...