packages feed

liquidhaskell-0.8.2.2: include/Language/Haskell/Liquid/Example.hs

{-@ LIQUID "--exact-data-cons" @-}
{-@ LIQUID "--higherorder"     @-}

module ListExample where

import NewProofCombinators

import Prelude hiding ((++))

--------------------------------------------------------------------------------
-- | Lists
--------------------------------------------------------------------------------
{-@ data L [size] @-}
data L a = C a (L a) | N

size :: L a -> Int
{-@ measure size @-}
{-@ size :: L a -> Nat @-}
size N       = 0
size (C _ x) = 1 + size x

--------------------------------------------------------------------------------
-- | Appending Lists
--------------------------------------------------------------------------------
{-@ reflect ++ @-}
{-@ infixr  ++ @-}
(++) :: L a -> L a -> L a
N ++ ys        = ys
(C x xs) ++ ys = C x (xs ++ ys)

--------------------------------------------------------------------------------
-- | Complete Proofs
--------------------------------------------------------------------------------
{-@ leftId :: x:L a -> { x ++ N == x } @-}
leftId :: L a -> Proof
leftId N
  =   N ++ N
  === N                        -- equality `N ++ N === N` holds by unfolding `++`
  *** QED

leftId (C x xs)
  =    (C x xs) ++ N
  ===  C x (xs ++ N)           -- equality holds by unfolding `++`
  ==? C x xs     ? leftId xs   -- equality requires "certificate" `leftId xs`
  *** QED


--------------------------------------------------------------------------------
-- | Incomplete Proofs
--------------------------------------------------------------------------------

{-@ assoc :: x:L a -> y:L a -> z:L a->  { (x ++ y) ++ z = x ++ (y ++ z) } @-}
assoc :: L a -> L a -> L a -> Proof
assoc N y z
  =   ()
  *** Admit                  -- Give up. Replace with QED to see ERROR.

assoc (C a x) y z
  =  ((C a x) ++ y) ++ z
  ==! C a (x ++ (y ++ z))    -- Unsafe-eq; replace with `==.` or `===` to see error )
  === (C a x) ++ (y ++ z)
  *** QED