packages feed

liquidhaskell-0.8.0.2: docs/slides/BOS14/lhs/07_Array.lhs

Abstract Refinements {#data}
============================

Recap
-----

<br>

**So far**

Abstract Refinements decouple invariants from *functions*

<br>

<div class="fragment">

**Next**

Decouple invariants from *indexed data structures*

</div>



Decouple Invariants From Data {#vector} 
=======================================

Example: Vectors 
----------------

<div class="hidden">
\begin{code}
module LiquidArray where

import Language.Haskell.Liquid.Prelude (liquidAssume, liquidError)

{-@ LIQUID "--no-termination" @-}
initialize :: Int -> Vec Int
\end{code}
</div>

<div class="fragment">

For simplicity, implemented as maps from `Int` to `a` 

<br>

\begin{code}
data Vec a = V (Int -> a)
\end{code}

</div>


Abstract *Domain* and *Range*
-----------------------------

Parameterize type with *two* abstract refinements:

<br>

\begin{code}
{-@ data Vec a < dom :: Int -> Prop,
                 rng :: Int -> a -> Prop >
      = V {a :: i:Int<dom> -> a <rng i>}  @-}
\end{code}

<br>

- `dom`: *domain* on which `Vec` is *defined* 

- `rng`: *range*  and relationship with *index*

Abstract *Domain* and *Range*
-----------------------------

Diverse `Vec`tors by *instantiating* `dom` and `rng`

<br>

<div class="fragment">

An alias for *segments* between `I` and `J`

<br>

\begin{code}
{-@ predicate Btwn I V J = I <= V && V < J @-}
\end{code}

</div>

Ex: Identity Vectors
--------------------

Defined between `[0..N)` mapping each key to itself:

<br>

<div class="fragment">

\begin{code}
{-@ type IdVec N = Vec <{\v -> Btwn 0 v N}, 
                        {\k v -> v = k}> 
                       Int                  @-}
\end{code}

</div>


Ex: Zero-Terminated Vectors
---------------------------

Defined between `[0..N)`, with *last* element equal to `0`:

<br>

<div class="fragment">

\begin{code}
{-@ type ZeroTerm N = 
     Vec <{\v -> Btwn 0 v N}, 
          {\k v -> k = N-1 => v = 0}> 
          Int                         @-}
\end{code}

</div>

Ex: Fibonacci Table 
-------------------

A vector whose value at index `k` is either 

- `0` (undefined), or, 

- `k`th fibonacci number 

\begin{code}
{-@ type FibV =  
     Vec <{\v -> true}, 
          {\k v -> v = 0 || v = fib k}> 
          Int                          @-}
\end{code}


An API for Vectors
------------------


<br>
<br>

- `empty`

- `set`

- `get`


API: Empty Vectors
-----------------

`empty` a Vector whose domain is `false` (defined at *no* key)

<br>

\begin{code}
{-@ empty :: forall <p :: Int -> a -> Prop>. 
               Vec <{v:Int|false}, p> a     @-}

empty     = V $ \_ -> error "empty vector!"
\end{code}

<br>

<div class="fragment">
<a href="http://goto.ucsd.edu:8090/index.html#?demo=Array.hs" target="_blank">Demo:</a>
What would happen if we changed `false` to `true`?
</div>

API: `get` Key's Value 
----------------------

- *Input* `key` in *domain*

- *Output* value in *range* related with `k`

<br>

\begin{code}
{-@ get :: forall a <d :: Int -> Prop,  
                     r :: Int -> a -> Prop>.
           key:Int <d>
        -> vec:Vec <d, r> a
        -> a<r key>                        @-}

get k (V f) = f k
\end{code}


API: `set` Key's Value 
----------------------

- <div class="fragment">Input `key` in *domain*</div>

- <div class="fragment">Input `val` in *range* related with `key`</div>

- <div class="fragment">Input `vec` defined at *domain except at* `key`</div>

- <div class="fragment">Output domain *includes* `key`</div>

API: `set` Key's Value 
----------------------

\begin{code}
{-@ set :: forall a <d :: Int -> Prop,
                     r :: Int -> a -> Prop>.
           key: Int<d> -> val: a<r key>
        -> vec: Vec<{v:Int<d>| v /= key},r> a
        -> Vec <d, r> a                     @-}

set key val (V f) = V $ \k -> if k == key 
                                then val 
                                else f k
\end{code}

<br>

<div class="hidden">
<a href="http://goto.ucsd.edu:8090/index.html#?demo=Array.hs" target="_blank">Demo:</a>
Help! Can you spot and fix the errors? 
</div>

Using the Vector API
--------------------

Loop over vector, setting each key `i` equal to `i`:

<br>

\begin{code}
{-@ initialize :: n:Nat -> IdVec n @-}
initialize n      = loop 0 empty
  where
    loop i a 
      | i < n     = let a' = set i i a
                    in
                        loop (i+1) a'
      | otherwise = a 
\end{code}

Example: Knuth-Morris-Pratt
---------------------------

<br>
<br>
<br>

[DEMO KMP.hs](../hs/KMP.hs)


Recap
-----

<br>

+ Created a `Vec` (Array) container 

+ Decoupled *domain* and *range* invariants from *data*

+ Enabled analysis of *array segments*

<br>

Recap
-----

<br>

Custom *array segment* program analyses: 

<br>

- Gopan-Reps-Sagiv, POPL 05
- J.-McMillan, CAV 07
- Logozzo-Cousot-Cousot, POPL 11
- Dillig-Dillig, POPL 12 

<br>

Encoded in (abstract) refinement typed API.


Recap
-----

1. Refinements: Types + Predicates
2. Subtyping: SMT Implication
3. Measures: Strengthened Constructors
4. Abstract: Refinements over Type Signatures
    + Functions
    + Recursive Data
    + <div class="fragment">**Indexed Data**</div>

<div class="fragment">[[continue...]](11_Evaluation.lhs.slides.html)</div>