0head and tail are SafeaverageLists Elementsmax Functionmax type (I)max type (II)max type (III)
Abstract Your Property Away to make the specification Modular!
max FunctionConsinder a monomorphic max function:
max :: Int -> Int -> Int
max x y = if x >= y then x else y
How can we refine the type of max?
max type (I)If max gets two Odd numbers:
max :: Odd -> Odd -> Odd
Then it returns an Odd number:
maxOdd :: Odd
maxOdd = max 3 7
max type (II)If max gets two Even numbers:
max :: Even -> Even -> Even
Then it returns an Even number:
maxEven :: Even
maxEven = max 40 42
max type (III)If max gets two Prime numbers:
max :: Prime -> Prime -> Prime
Then it returns a Prime number:
maxPrime :: Prime
maxPrime = max 7 13
So, what is the primal type of max?
max :: Odd -> Odd -> Odd
max :: Even -> Even -> Even
max :: Prime -> Prime -> Prime
max returns one of its two inputs x and y.
This holds, regardless of what that property was!
{-@ max :: forall <p :: Int -> Prop>.
Int<p> -> Int<p> -> Int<p> @-}
max :: Int -> Int -> Int
max x y = if x <= y then y else x
Where
Int<p> is just an abbreviation for {v:Int | (p v)}
This type states explicitly:
p, that is a property on Int,max takes two inputs that satisfy p,max returns an output that satisfies p.
max with two arguments with the same concrete refinement,p will be automagically instantiated with that concrete refinement,{-@ type Odd = {v:Int | (v mod 2) = 1} @-}
{-@ maxOdd :: Odd @-}
maxOdd = max 3 5
Abstract The Property Away to make the specification Modular!
Then, instantiate the property back to get your specification.
Previously we saw how to refine the list data definition to get ordered lists:
{-@ data OList a =
OEmp
| (:<:) { oHd :: a
, oTl :: OList {v:a | oHd <= v}} @-}
Just abstract the property away!
Every element of the tail recursively satisfies p on the head!
Use increasing lists
to specify insertion sort, as before!
Haskell build-in list comes parameterized for you!
You can just instantiate the abstract refinement!
And prove recursive list properties!
{-@ descending :: x:a -> IList {v:a | x < v} -> [a] -> [IList a] @-}
{-@ ascending :: x:a -> (IList {v:a|v>=x} -> IList a) -> [a] -> [IList a] @-}
Next:Bounded Refinements