0
head
and tail
are Safeaverage
List
s Elementsmax
Functionmax
type (I)max
type (II)max
type (III)
Lets define our own List
data type:
Measure
Haskell function with a single equation per constructor
Measure
Strengthens type of data constructor
data List a where
Emp :: {v:List a | length v = 0}
(:::) :: x:a -> xs:List a
-> {v:List a | length v = 1 + length xs}
Fear head
and tail
no more!
Q: Write types for head
and tail
that verify impossible
.
A convenient type alias
average
Q: Write type for avg
that verifies safe division.
Hence, we can write Set-valued measures
Using the Data.Set
API for convenience
import qualified Data.Set as S
List
s Elementsinline
lets us reuse Haskell terms in refinements.
Measure
Strengthens type of data constructor
data List a where
Emp :: {v:List a | length v == 0
&& elems v == S.empty}
(:::) :: x:a -> xs:List a
-> {v:List a | length v == 1 + length xs
&& elems v == addElem v xs }
Can we specify sortedness?
Make illegal states unrepresentable
Lets define a type for ordered lists
Lets refine the type to enforce order
Head oHd
is smaller than every value v
in tail oTl
Illegal values unrepresentable
Q: Oops. There's a problem! Can you fix it?
Unlike indexed types, measures ...
Decouple properties from data type
Reuse same data type with different invariants
Limited to decidable logics but ...
Offer massive amounts of automation
Compare with insertionSort
in:
Problem: How to reason about elems
and lenght
of an OList
?
Solution: Make OList
an instance of List
using Abstract Refinements!
Next: Abstract Refinements