a @-}
set key val (V f) = V $ \k -> if k == key
then val
else f key
\end{code}
Demo:
Help! Can you spot and fix the errors?
Using the Vector API
--------------------
Memoized Fibonacci
------------------
Use `Vec` API to write a *memoized* fibonacci function
\begin{code} Using the fibonacci table:
type FibV =
Vec <{\v -> true},
{\k v -> (v = 0 || v = (fib k))}>
Int
\end{code}
But wait, what is `fib` ?
Specifying Fibonacci
--------------------
`fib` is *uninterpreted* in the refinement logic
\begin{code}
{-@ measure fib :: Int -> Int @-}
\end{code}
Specifying Fibonacci
--------------------
We *axiomatize* the definition of `fib` in SMT ...
\begin{code}
predicate AxFib I =
(fib I) == if I <= 1
then 1
else fib(I-1) + fib(I-2)
\end{code}
Specifying Fibonacci
--------------------
Finally, lift axiom into LiquidHaskell as *ghost function*
\begin{code}
{-@ axiom_fib ::
i:_ -> {v:_|((Prop v) <=> (AxFib i))} @-}
\end{code}
**Note:** Recipe for *escaping* SMT limitations
1. *Prove* fact externally
2. *Use* as ghost function call
Fast Fibonacci
--------------
An efficient fibonacci function
\begin{code}
{-@ fastFib :: n:Int -> {v:_ | v = (fib n)} @-}
fastFib n = snd $ fibMemo (V (\_ -> 0)) n
\end{code}
- `fibMemo` *takes* a table initialized with `0`
- `fibMemo` *returns* a table with `fib` values upto `n`.
Memoized Fibonacci
------------------
\begin{code}
fibMemo t i
| i <= 1
= (t, liquidAssume (axiom_fib i) 1)
| otherwise
= case get i t of
0 -> let (t1,n1) = fibMemo t (i-1)
(t2,n2) = fibMemo t1 (i-2)
n = liquidAssume
(axiom_fib i) (n1+n2)
in (set i n t2, n)
n -> (t, n)
\end{code}
Memoized Fibonacci
------------------
- `fibMemo` *takes* a table initialized with `0`
- `fibMemo` *returns* a table with `fib` values upto `n`.
\begin{code}
{-@ fibMemo :: FibV
-> i:Int
-> (FibV,{v:Int | v = (fib i)}) @-}
\end{code}
Recap
-----
Created a `Vec` container
Decoupled *domain* and *range* invariants from *data*
Previous, special purpose program analyses
- [Gopan-Reps-Sagiv, POPL 05](link)
- [J.-McMillan, CAV 07](link)
- [Logozzo-Cousot-Cousot, POPL 11](link)
- [Dillig-Dillig, POPL 12](link)
- ...
Encoded as instance of abstract refinement types!