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