module BoundedRefinements () where
import Prelude hiding ((++), (.))
import Language.Haskell.Liquid.Prelude
{-@ type IList a = [a]<{\hd tl -> hd <= tl}> @-}
append :: Ord a => a -> [a] -> [a] -> [a]
qsort1 :: Ord a => [a] -> [a]
-- chain :: (b -> c -> Bool) -> (a -> b -> Bool) -> (a -> c -> Bool) -> a -> b -> c -> Bool
recProp :: (a -> Bool) -> (a -> Bool) -> (a -> a -> Bool) -> a -> a -> Bool
Bounded Refinement Types
Relating Abstract Refinements
Verification of QuickSort (I)
{-@ qsort1 :: xs:[a] -> IList a @-}
qsort1 [] = []
qsort1 (x:xs) = append1 listLess (x:listGEq)
where
listLess = qsort1 [y | y <- xs, y < x]
-- :: IList {y:a | y < x}
listGEq = qsort1 [z | z <- xs, z >= x]
-- :: IList {y:a | y < x}
{-@ append :: x:a
-> IList {hd:a | hd < x}
-> IList {tl:a | x <= tl}
-> IList a @-}
append _ [] ws = ws
append x (y:ys) ws = y:append x ys ws
Verification requirement:
hdProp = \hd -> hd < x -- property of head elements
tlProp = \tl -> x <= tl -- property of tail elements
----------------------------------------------------------
recProp = \hd tl -> hd <= tl -- recursive (sorted) list
Abstracting over Properties:
forall hd tl. hdProp hd => tlProp tl => recProp hd tl
Note: Abstract requirement is independent of x!
Bounds on Abstract Refinements
Turn Requirement:
forall hd tl. hdProp hd => tlProp tl => recProp hd tl
Into a Bound: Haskell function that relates abstract refinements
{-@ (++) :: forall < hdprop :: a -> Bool
, tlprop :: a -> Bool
, p :: a -> a -> Bool>.
{hd :: a < hdprop >|- a< tlprop > <: a < p hd >}
[a< hdprop >]< p > -> [a< tlprop >]< p > -> [a]< p > @-}
(++) [] ys = ys
(++) (x:xs) ys = x:(xs ++ ys)
Bound RecProp combines
the recursive property p
the property of each head hdprop
the property of tail elements tlprop
Bound Instantiations
{-@ qsort :: xs:[a] -> IList a @-}
qsort [] = []
qsort (x:xs) = listLess ++ (x:listGEq)
-- :: IList a == [a]<{\hd tl -> hd <= tl}>
where
listLess = qsort [y | y <- xs, y < x ]
-- :: IList {y:a | y < x}
listGEq = qsort [z | z <- xs, z >= x]
-- :: IList {z:a | x <= z}
Abstract Refinement Instantiation:
recProp = \hd tl -> hd <= tl -- recursive (sort) property
hdProp = \hd -> hd < x -- property of head elements
tlProp = \tl -> x <= tl -- property of tail elements
Bound Instantiation:
recProp
= \hd tl -> hd < x ==> x <= tl ==> hd <= tl
Recap
Refinements: Types + Predicates
Subtyping: SMT Implication
Measures: Specify Properties of Data
Abstract Refinements: Decouple properties from code