0
head
and tail
are Safeaverage
List
s 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