{-@ LIQUID "--no-termination" @-}
{-@ LIQUID "--short-names" @-}
module AbstractingRefinements ( insertSort ) where
import Prelude hiding (foldr)
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f b [] = b
foldr f b (x:xs) = f x (foldr f b xs)
Invariants In Constructors
Many many possibilities ...
Invariants In Constructors
Lets specify ordered lists:
data OList a = Emp
| (:<) { hd :: a
, tl :: OList a }
infixr 9 :<
{-@ data OList a = Emp
| (:<) { hd :: a
, tl :: OList {v:a | hd <= v}}
@-}
Invariants In Constructors
Make illegal values unrepresentable!
ok :: OList Int
ok = 1 :< 2 :< 3 :< Emp
bad :: OList Int
bad = 1 :< 3 :< 2 :< Emp
data [a]<p :: a -> a -> Prop> where
= []
| (:) { hd :: a
, tl :: [{v:a | p hd v}]}
Abstracting Refinements
Instantiate refinements to get different invariants!
{-@ type Incrs a = [a]<{\x y -> x <= y}> @-}
{-@ type Decrs a = [a]<{\x y -> x >= y}> @-}
{-@ type Diffs a = [a]<{\x y -> x /= y}> @-}
Using Abstract Refinements
Inference FTW!
{-@ insertSort :: (Ord a) => [a] -> Incrs a @-}
insertSort xs = foldr insert [] xs
insert x [] = [x]
insert x (y:ys)
| x < y = x : y : ys
| otherwise = y : insert x ys