{-@ 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
Invariants In Constructors
Make illegal values unrepresentable!
But its tedious to have multiple list types ...
Abstracting Refinements
Parameterize types over refinements!
Abstracting Refinements
Parameterize types over refinements!
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
Recap
Abstract Refinements
Parametric Polymorphism for Refinement Types
Recap
Abstract Refinements
Parametric Polymorphism for Refinement Types
Bounded Refinements
Bounded Quantification for Refinement Types
Bounded Refinements: Induction as a Type
The boundInductive says relation step preserves inv
Inductive inv step = \y ys acc v ->
inv ys acc ==> step y acc v ==> inv (y:ys) v
Bounded Refinements: Induction as a Type
The boundInductive says relation step preserves inv
Inductive inv step = \y ys acc v ->
inv ys acc ==> step y acc v ==> inv (y:ys) v
Key Idea
Bound is a Horn Clause over (Abstract) Refinements
Bounded Refinements: Induction as a Type
The type of foldr encodes induction over lists ...