Lazy Evaluation
SMT based Verification
Techniques developed for strict languages
Floyd-Hoare |
: |
ESCJava , SpecSharp ... |
Model Checkers |
: |
Slam , Blast ... |
Refinement Types |
: |
DML , Stardust , Sage , F7 , F* , ... |
Surely soundness carries over to Haskell, right?
An Innocent Function
foo
returns a value strictly less than input.
90: {-@ foo :: n:Nat -> {v:Nat | v < n} @-}
91: foo n
92: | n > 0 = n 1
93: | otherwise = foo n
Safe With Eager Eval
122: {-@ foo :: n:Nat -> {v:Nat | v < n} @-}
123: foo n
124: | n > 0 = n 1
125: | otherwise = foo n
126:
127: explode = let z = 0
128: a = foo z
129: in
130: (\x -> 2013 `safeDiv` z) a
Safe in Java, ML: program spins away, never hits divide-by-zero
Unsafe With Lazy Eval
143: {-@ foo :: n:Nat -> {v:Nat | v < n} @-}
144: foo n
145: | n > 0 = n 1
146: | otherwise = foo n
147:
148: explode = let z = 0
149: a = foo z
150: in
151: (\x -> 2013 `safeDiv` z) a
Unsafe in Haskell: program skips foo z
and hits divide-by-zero!
Problem: Divergence
What is denoted by:
e :: {v:Int | P}
e
evaluates to Int
satisfying P
Problem: Divergence
Consider
191: {-@ e :: {v : Int | P} @-}
192:
193: let x = e in body
Eager Evaluation
Can assume
P(x)
when checking
body
Lazy Evaluation
Cannot assume
P(x)
when checking
body
Eager vs. Lazy Binders
216: {-@ foo :: n:Nat -> {v:Nat | v < n} @-}
217: foo n
218: | n > 0 = n 1
219: | otherwise = foo n
220:
221: explode = let z = 0
222: a = foo z
223: in
224: (\x -> 2013 `safeDiv` z) a
Inconsistent refinement for a
is sound for eager, unsound for lazy
Panic! Now what?
Solution
Assign
non-trivial refinements to
non-diverging terms!
Require A Termination Analysis
Don't worry, its easy...
Demo: Disable
"--no-termination"
and see what happens!
Recap
- Refinements: Types + Predicates
- Subtyping: SMT Implication
- Measures: Strengthened Constructors
- Abstract: Refinements over functions and data
- Lazy Evaluation: Requires Termination
Termination: via Refinements!