packages feed

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

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

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

module ConcatMap where

import Axiomatize
import Equational 
import Prelude hiding (map, concatMap, concat)

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 append @-}
$(axiomatize
  [d| append :: L a -> L a -> L a 
      append N ys        = ys 
      append (C x xs) ys = C x (append xs ys)
    |])

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

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


{-@ axiomatize concatt @-}

$(axiomatize
  [d| concatt :: L (L a) -> L a 
      concatt N        = N 
      concatt (C x xs) = append x (concatt xs)
     |])


--   "concat/map" forall f xs . concat $ map f xs = concatMap f xs

{-@ prop_concatMap :: f:(a -> L (L a)) -> xs:L a
                   -> {v:Proof | (concatt (map f xs) == concatMap f xs) }  @-}

prop_concatMap :: Eq a => (a -> L (L a)) -> L a -> Proof  
prop_concatMap f xs
   = cases 2 (concatt (map f xs) == concatMap f xs)

{- 
prop_concatMap f (C x xs)
   = auto 1 (concatt (map f (C x xs)) == concatMap f (C x xs))
-} 
-- prop_concatMap f N
--    = auto 1 (concatt (map f N) == concatMap f N)
--   = refl e1 `by` pr1 `by` pr2 `by` pr3 
{- 
  where
    e1  = concatt (map f N)
    pr1 = axiom_map_N f
    e2  = concatt N
    pr2 = axiom_concatt_N
    e3  = N
    pr3 = axiom_concatMap_N f 
    e4  = concatMap f N
-}

-- prop_concatMap f (C x xs) 
--   = auto 2 (concatt (map f (C x xs)) == concatMap f (C x xs))
{-
  = refl e1 `by` pr1 `by` pr2 `by` pr3 `by` pr4 
  where 
    e1  = concatt (map f (C x xs)) 
    pr1 = axiom_concatt_C (f x) (map f xs)
    pr2 = axiom_concatMap_C f x xs 
    pr3 = axiom_map_C f x xs 
    pr4 = prop_concatMap f xs  
-}

{-@ 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