liquidhaskell-0.8.2.0: docs/slides/flops14/lhs/04_AbstractRefinements.lhs
{#abstractrefinements}
========================
<div class="hidden">
\begin{code}
module AbstractRefinements where
import Prelude
import Language.Haskell.Liquid.Prelude
{-@ LIQUID "--no-termination" @-}
o, no :: Int
maxInt :: Int -> Int -> Int
\end{code}
</div>
Abstract Refinements
--------------------
Abstract Refinements
====================
Two Problems
------------
<br>
<br>
<div class="fragment">
**Problem 1:**
How do we specify *both* increasing and decreasing lists?
</div>
<br>
<div class="fragment">
**Problem 2:**
How do we specify *iteration-dependence* in higher-order functions?
</div>
Problem Is Pervasive
--------------------
Lets distill it to a simple example...
<div class="fragment">
<br>
(First, a few aliases)
<br>
\begin{code}
{-@ type Odd = {v:Int | (v mod 2) = 1} @-}
{-@ type Even = {v:Int | (v mod 2) = 0} @-}
\end{code}
</div>
Example: `maxInt`
-----------------
Compute the larger of two `Int`s:
\begin{code} <br>
maxInt :: Int -> Int -> Int
maxInt x y = if y <= x then x else y
\end{code}
Example: `maxInt`
-----------------
Has **many incomparable** refinement types
\begin{code}<br>
maxInt :: Nat -> Nat -> Nat
maxInt :: Even -> Even -> Even
maxInt :: Odd -> Odd -> Odd
\end{code}
<br>
<div class="fragment">Oh no! **Which** one should we use?</div>
Refinement Polymorphism
-----------------------
`maxInt` returns *one of* its two inputs `x` and `y`
<div class="fragment">
<div align="center">
<br>
--------- --- -------------------------------------------
**If** : the *inputs* satisfy a property
**Then** : the *output* satisfies that property
--------- --- -------------------------------------------
<br>
</div>
</div>
<div class="fragment">Above holds *for all properties*!</div>
<br>
<div class="fragment">
**Need to abstract properties over types**
</div>
<!--
By Type Polymorphism?
---------------------
\begin{code} <br>
max :: α -> α -> α
max x y = if y <= x then x else y
\end{code}
<div class="fragment">
Instantiate `α` at callsites
\begin{code}
{-@ o :: Odd @-}
o = maxInt 3 7 -- α := Odd
{-@ e :: Even @-}
e = maxInt 2 8 -- α := Even
\end{code}
</div>
By Type Polymorphism?
---------------------
\begin{code} <br>
max :: α -> α -> α
max x y = if y <= x then x else y
\end{code}
<br>
But there is a fly in the ointment ...
Polymorphic `max` in Haskell
----------------------------
\begin{code} In Haskell the type of max is
max :: (Ord α) => α -> α -> α
\end{code}
<br>
\begin{code} Could *ignore* the class constraints, instantiate as before...
{-@ o :: Odd @-}
o = max 3 7 -- α := Odd
\end{code}
Polymorphic `(+)` in Haskell
----------------------------
\begin{code} ... but this is *unsound*!
max :: (Ord α) => α -> α -> α
(+) :: (Num α) => α -> α -> α
\end{code}
<br>
<div class="fragment">
*Ignoring* class constraints would let us "prove":
\begin{code}
{-@ no :: Odd @-}
no = 3 + 7 -- α := Odd !
\end{code}
</div>
Type Polymorphism? No.
----------------------
<div class="fragment">Need to try a bit harder...</div>
-->
Parametric Refinements
----------------------
Enable *quantification over refinements* ...
<br>
<div class="fragment">
\begin{code}
{-@ maxInt :: forall <p :: Int -> Prop>.
Int<p> -> Int<p> -> Int<p> @-}
maxInt x y = if x <= y then y else x
\end{code}
</div>
<br>
<div class="fragment">Type says: **for any** `p` that is a property of `Int`, </div>
- <div class="fragment">`max` **takes** two `Int`s that satisfy `p`,</div>
- <div class="fragment">`max` **returns** an `Int` that satisfies `p`.</div>
Parametric Refinements
----------------------
Enable *quantification over refinements* ...
<br>
\begin{code}<div/>
{-@ maxInt :: forall <p :: Int -> Prop>.
Int<p> -> Int<p> -> Int<p> @-}
maxInt x y = if x <= y then y else x
\end{code}
<br>
[Key idea: ](http://goto.ucsd.edu/~rjhala/papers/abstract_refinement_types.html) `Int<p>` is just `{v:Int | (p v)}`
<br>
i.e., Abstract Refinement is an **uninterpreted function** in SMT logic
Parametric Refinements
----------------------
\begin{code}<br>
{-@ maxInt :: forall <p :: Int -> Prop>.
Int<p> -> Int<p> -> Int<p> @-}
maxInt x y = if x <= y then y else x
\end{code}
<br>
**Check** and **Instantiate**
Using [SMT and Abstract Interpretation.](http://goto.ucsd.edu/~rjhala/papers/liquid_types.html)
Using Abstract Refinements
--------------------------
- <div class="fragment">**When** we call `maxInt` with args with some refinement,</div>
- <div class="fragment">**Then** `p` instantiated with *same* refinement,</div>
- <div class="fragment">**Result** of call will also have *same* concrete refinement.</div>
<div class="fragment">
\begin{code}
{-@ o' :: Odd @-}
o' = maxInt 3 7 -- p := \v -> Odd v
{-@ e' :: Even @-}
e' = maxInt 2 8 -- p := \v -> Even v
\end{code}
</div>
Using Abstract Refinements
--------------------------
Or any other property ...
<br>
<div class="fragment">
\begin{code}
{-@ type RGB = {v:_ | (0 <= v && v < 256)} @-}
{-@ rgb :: RGB @-}
rgb = maxInt 56 8 -- p := \v -> 0 <= v < 256
\end{code}
</div>
Recap
-----
1. Refinements: Types + Predicates
2. Subtyping: SMT Implication
3. Measures: Strengthened Constructors
4. **Abstract Refinements** over Types
<br>
<br>
<div class="fragment">
Abstract Refinements are *very* expressive ... <a href="06_Inductive.lhs.slides.html" target="_blank">[continue]</a>
</div>