-
Notifications
You must be signed in to change notification settings - Fork 150
Open
Description
I was playing with the infinite list data structure described in the ICFP '14 paper (section 5.2) in order to explore how Liquid Haskell handles non-termination. I've got the following definition for infinite list (based on the original definition from the paper):
{-@ data L [length] a <p :: L a -> Bool> = N | C { x :: a, xs :: L<p> a <<p>> } @-}
data L a = N | C a (L a)
{-@ type Stream a = {xs: L <{\v -> not (emp v)}> a | not (emp xs) } @-}
{-@ measure length @-}
{-@ length :: L a -> Nat @-}
length :: L a -> Int
length N = 0
length (C _ xs) = 1 + length xs
{-@ reflect emp @-}
emp :: L a -> Bool
emp N = True
emp (C x xs) = False
Then @goldfirere and I wrote the following proof, which was successfully verified:
-- Proof that Stream is infinite
{-@ thmStreamInf :: xs:Stream a -> { 1 == 2 } @-}
thmStreamInf :: L a -> Proof
thmStreamInf N = error "never happens"
thmStreamInf (C x xs) = thmStreamInf xs *** QED
Consequently, we could use thmStreamInf to prove {1 == 2}, for example:
{-@ silly :: { 1 == 2 } @-}
silly = thmStreamInf (repeat 3)
{-@ lazy repeat @-}
{-@ repeat :: a -> Stream a @-}
repeat x = C x (repeat x)
Now we could prove something that's simply false, for example:
{-@ abs :: Int -> Nat @-}
abs :: Int -> Int
abs x = x
where the definition of abs does not always return a Nat.
Any thoughts on why this might have happened? In particular, what are the exact reasons why thmStreamInf was verified?
Metadata
Metadata
Assignees
Labels
No labels