a -> Prop>. Vec < {v:Int | 0=1}, p> a @-}
empty :: Vec a
empty = V $ \_ -> (error "Empty array!")
\end{code}
Typing Get
----------
If `i` satisfies the domain then
if we `get` the `i`th element of an array,
the result should satisfy the range at `i`
\begin{code}
{-@ get :: forall a
\begin{code}
{-@ set :: forall a
Where `fib` is an *uninterprented function*
\begin{code}
{-@ measure fib :: Int -> Int @-}
\end{code}
We used `fib` to define the `axiom_fib`
\begin{code}
{-@ predicate Fib I =
(fib i) = (if (i <= 1) then 1 else ((fib (i-1)) + (fib (i-2))))
@-}
{-@ assume axiom_fib :: i:Int -> {v: Bool | ((Prop v) <=> (Fib i))} @-}
axiom_fib :: Int -> Bool
axiom_fib i = undefined
\end{code}
Fast Fibonacci
--------------
Now we can efficiently compute the `i`th fibonacci number
\begin{code}
{-@ fastFib :: x:Int -> {v:Int | v = fib(x)} @-}
fastFib :: Int -> Int
fastFib n = snd $ fibMemo (V (\_ -> 0)) n
\end{code}
Fibonacci Memo
--------------
\begin{code}
{-@ fibMemo :: FibV -> i:Int -> (FibV, {v: Int | v = (fib i)}) @-}
fibMemo :: Vec Int -> Int -> (Vec Int, Int)
fibMemo t i
| i <= 1
= (t, liquidAssume (axiom_fib i) (1 :: Int))
| 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}