True
is a bad argument10
is a good argument0
fib
is an uninterpreted function0
average
take
fib
fib
is an uninterpreted function
How we express and prove properties on ADTs?
A user defined list,
with its anchored size function.
The Liquid pragma
Automatically creates checker and selector measures:
isN :: L a -> Bool
isC :: L a -> Bool
select_C_1 :: L a -> a
select_C_2 :: L a -> L a
Q: Do these function types look familiar?
map
reflects into logic! map
reflects in its result type map :: f:(a->b) -> xs:L a
-> {v:L a | v == map f xs
&& v == if isN xs then N else
C (f (select_C_1 xs)
(map f (select_C_2 xs))
}
Non-recursive functions reflect too!
Get automatically the "singleton" Liquid Types:
id :: x:a -> {v:a | v == id x && v == x}
compose :: f:(b -> c) -> g:(a -> b) -> x:a
-> {v:c | v == compose f g x && v == f (g x)}
Lets prove the identity functor law!
Proof:
Lets prove the distribution functor law!
Or, mapFusion
!
Hints (surprise!)
Here is the proof:
mapFusion f g N
= map (compose f g) N
==. N
==. map f N
==. map f (map g N)
==. (compose (map f) (map g)) N
*** QED
mapFusion f g (C x xs)
= map (compose f g) (C x xs)
==. (compose f g) x `C` map (compose f g) xs
==. compose f g x `C` map (compose f g) xs
==. f (g x) `C` (compose (map f) (map g)) xs
? mapFusion f g xs
==. f (g x) `C` compose (map f) (map g) xs
==. f (g x) `C` (map f) ((map g) xs)
==. f (g x) `C` map f (map g xs)
==. map f (g x `C` map g xs)
==. map f (map g (C x xs))
==. compose (map f) (map g) (C x xs)
*** QED
Reflect the monoid list operators
Lets prove the left identity monoid law!
Hints:
emptyLeft x
= append empty x ==. append N x ==. x *** QED
Lets prove the right identity monoid law!
Hints (surprise, surprise!)
emptyRight N
= append N empty
==. append N N
==. N
*** QED
emptyRight (C x xs)
= append (C x xs) empty
==. x `C` append xs empty
==. x `C` xs ? emptyRight xs
*** QED
Lets prove the associativity monoid law!
Proof (surprise!)
Define monad list operators
Lets prove the left identity monad law!
Hint
emptyRight
on f x
leftIdentity x f
= bind (return x) f
==. bind (C x N) f
==. append (f x) (bind N f)
==. append (f x) N
==. append (f x) empty
==. f x ? emptyRight (f x)
*** QED
Lets prove the right identity monad law!
Proof
emptyLeft
on xs
.
To prove associativity, lets assume two helper lemmata!
βequivalence :: f:(a -> L b) -> g:(b -> L c) -> x:a ->
{bind (f x) g == (\y:a -> bind (f y) g) (x)}
bindAppend :: xs:L a -> ys:L a -> f:(a -> L b)
-> { bind (append xs ys) f == append (bind xs f) (bind ys f) }
Lets prove the associativity monad law!
Hint
... so, we teach SMT β-equivalence via Liquid pragma.
A final boring inductive proof...
map id == id
map (compose f g) == compose (map f) (map g)
append empty x == x
append x empty == x
append xs (append ys zs) == append (append xs ys) zs
bind (return x) f == f x
bind x return == x
bind (bind m f) g == bind m (\x:a -> (bind (f x) g))
Next: Case Study: MapReduce: Program Properties that matter!