packages feed

liquidhaskell-0.8.0.2: tests/equationalproofs/pos/MapAppend.hs

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ExtendedDefaultRules #-}

{-@ LIQUID "--autoproofs"      @-}
{-@ LIQUID "--totality"        @-}
{-@ LIQUID "--exact-data-cons" @-}

module Append where

import Axiomatize
import Equational 
import Prelude hiding (map)

data L a = N |  C a (L a)

instance Eq a => Eq (L a) where
  N == N                 = True
  (C x xs) == (C x' xs') = x == x' && xs == xs'

{-@ axiomatize map @-}
$(axiomatize
  [d| map :: (a -> b) -> L a -> L b
      map f N        = N
      map f (C x xs) = C (f x) (map f xs) 
    |])


{-@ axiomatize append @-}
$(axiomatize
  [d| append :: L a -> L a -> L a 
      append N ys        = ys 
      append (C x xs) ys = C x (append xs ys)
    |])



--   "map/append" forall f xs ys. map f (xs ++ ys) = map f xs ++ map f ys
{-@ prop_map_append ::  f:(a -> a) -> xs:L a -> ys:L a 
                    -> {v:Proof | map f (append xs ys) == append (map f xs) (map f ys) }
  @-}
prop_map_append :: Eq a => (a -> a) -> L a -> L a -> Proof
-- prop_map_append f N ys = auto 2 (map f (N `append` ys) == map f N `append` map f ys) 
-- prop_map_append f N ys = auto 2 (map f (N `append` ys) == map f N `append` map f ys) 
prop_map_append f xs ys = cases 2 (map f (xs `append` ys) == map f xs `append` map f ys) 

{- Generated axioms: 
1. axiom_append_N (map f ys)
2. axiom_append_N ys 
3. axiom_map_N f 
-}  

{-  
prop_map_append f (C x xs) ys = 
  auto 2  (map f (append (C x xs) ys) == append (map f (C x xs)) (map f ys))
  -- refl (append (map f (C x xs)) (map f ys))
  --   `by` pr1 `by` pr2 `by` pr3 `by` pr4 `by` pr5 
    where
      e1  = append (map f (C x xs)) (map f ys)
      pr1 = axiom_map_C f x xs
      e2  = append (C (f x) (map f xs)) (map f ys)
      pr2 = axiom_append_C  (map f ys) (f x) (map f xs)
      e3  = C (f x) (append (map f xs) (map f ys))
      pr3 = prop_map_append f xs ys
      e4 = C (f x) (map f (append xs ys))
      pr4 = axiom_map_C f x (append xs ys)
      e5  = map f (C x (append xs ys))
      pr5 = axiom_append_C ys x xs
      e6  = map f (append (C x xs) ys)
-}


{-@ data L [llen] @-}
{-@ invariant {v: L a | llen v >= 0} @-}

{-@ measure llen @-}
llen          :: L a -> Int
llen N        = 0
llen (C x xs) = 1 + llen xs