Download presentation

Presentation is loading. Please wait.

Published byAnthony Alder Modified over 2 years ago

1
HASKELL TO LOGIC THROUGH DENOTATIONAL SEMANTICS Dimitrios Vytiniotis, Koen Claessen, Simon Peyton Jones, Dan Rosén POPL 2013, January

2
Real programs contain assertions grep -i ASSERT./*hs./FamInst.lhs: = ASSERT( isAlgTyCon tycon )./Inst.lhs: ; wrap <- ASSERT( null rest && isSingleton theta )./TcCanonical.lhs: = ASSERT( tyConArity tc <= length tys )-- Type functions are saturated./TcCanonical.lhs: = ASSERT( not (isKind t1) && not (isKind t2) )./TcClassDcl.lhs: = ASSERT( ok_first_pred ) local_meth_ty./TcClassDcl.lhs: rho_ty = ASSERT( length sel_tyvars == length inst_tys )./TcDeriv.lhs: ASSERT( null sigs )./TcDeriv.lhs: = ASSERT2( equalLength rep_tc_tvs all_rep_tc_args, ppr cls ppr rep_tc )./TcDeriv.lhs: arg_ty <- ASSERT( isVanillaDataCon data_con )./TcEnv.lhs: -> ASSERT( lvl == lvl1 ) id./TcEnv.lhs: TopLevel -> ASSERT2( isEmptyVarSet id_tvs, ppr id $$ ppr (idType id) )./TcErrors.lhs: = ASSERT( isEmptyBag insols )./TcErrors.lhs: = ASSERT( not (null matches) )./TcErrors.lhs: = ASSERT( length matches > 1 )./TcEvidence.lhs: | otherwise = ASSERT( arity < n_tys )./TcEvidence.lhs:mkTcForAllCo tv (TcRefl ty) = ASSERT( isTyVar tv ) TcRefl (mkForAllTy tv ty)./TcEvidence.lhs:mkTcForAllCo tv co = ASSERT( isTyVar tv ) TcForAllCo tv co./TcEvidence.lhs:mkTcForAllCos tvs (TcRefl ty) = ASSERT( all isTyVar tvs ) TcRefl (mkForAllTys tvs ty)./TcEvidence.lhs:mkTcForAllCos tvs co = ASSERT( all isTyVar tvs ) foldr TcForAllCo co tvs./TcEvidence.lhs: = ASSERT (tc `hasKey` eqTyConKey)./TcEvidence.lhs: = ASSERT( equalLength tvs cos )./TcExpr.lhs: = ASSERT( not (isSigmaTy res_ty) )./TcExpr.lhs: = ASSERT( notNull upd_fld_names ) (from the GHC type checker) 2

3
This work Automated static verification of higher- order functional programs Tool works on subset of Haskell, uses GHC as frontend 3

4
Our setting Verify Haskell code: higher-order, lazy but pure Dont aim for high expressiveness, go for simple, easy-to-prove (e.g. structural) properties Automatically discharge all tedious but simple goals that a programmer has to manually and repeatedly check Re-use existing technology: Automated theorem provers (e.g. SMT solvers), model finders ACL2? Boogie? Prolog? Property-directed reachability? [Bjorner et al] No best solution yet. Our choice for this work 4

5
Programs and properties risers [] = [] risers [x] = [[x]] risers (x:y:ys) = case risers (y:ys) of [] -> error urk (s:ss) -> if x <= y then (x:s):ss else [x]:s:ss 1.can risers crash? 2.non-empty input non-empty result? Syntax of contracts (refinements more appropriate): C ::= {x | p} | (x:C1)->C2 | C1 && C2 | CF Just an ordinary Haskell expression of type Bool crash-free 5

6
Design module Foo f x y = … g x = … -- Prelude data [a] = [] | a : as data Bool = True | False … Functions over these… Haskell Source First Order Logic Formulae Unsatisfiable Contract holds! HALO translation to First Order Logic Z3/Equinox/E/ Vampire/Paradox Theorem Prover Satisfiable Probably contract doesnt hold but who knows Cant tell anything 6

7
Key idea: let denotational semantics guide us A λ/case-lifted language Continuous function space Distinguished one-element cpo Lifting 7

8
Interpreted as injection into the appropriate product 8

9
Function definitions become FOL axioms head (Cons x xs) = x head _ = error 9

10
data List a = Cons a (List a)| Nil 10

11
Higher-order functions head (Cons x xs) = x head _ = error double f x = f (f x) 11

12
Refinements denotationally and logically Logically Denotationally 12

13
Soundness via denotational semantics 13

14
Automating induction Currently support fixpoint induction Assume contract holds for uninterpreted function add_rec NB: A sound thing to do by admissibility of contracts 14

15
Admissibility and why it matters In Haskell, data types are not inductive. Hence your familiar induction principle is simply unsound! ones = 1 : ones f Z = [] f (S x) = 1 : f x Lemma: forall x. f x ones Proof: Holds for UNR Holds for Z Assume holds for x; then holds for (S x) Right? WRONG! Let: u = S u Then: f u = ones Logical inequality, not admissible! 15

16
Admissibility and induction Admissibility = If P is true for all elements of a chain, then true for the limit. Not all predicates are admissible Comes for-free! Base contracts are Haskell functions, and those are continuous! 16

17
Happily implemented on top of GHC API Z3 rocks for provable properties! Disclaimer: FOL axioms/problem Use of fixpoint induction 17

18
More features (and non-features) More features: Incremental verification Prove spec for g, use either the spec or definition of g, or both to prove other specifications … Some support for lemmas Mutual (automatic) fixpoint induction Primitive arithmetic constraints via SMT2 (in Z3) Experimental features: logical equality, finite unfoldings Not there: Pre/post inference, strengthening of IH Support for counterexamples (see next slide) 18

19
Whats next: counterexamples 19 Unprovable contracts (because theyre false or were incomplete) Paradox Equinox Z3 Vampire E-prover AnyMorphism.big_sat_app_any_morphism_fail_step P:---- X:---- Z:---- V:---- E:---- Loop.sat_id_loop_pred P:0.00 X:0.01 Z:0.01 V:---- E:0.01 Loop.sat_id_recursive_true P:---- X:---- Z:---- V:---- E:0.01 PredLog.sat_concatMap_cf_missing_step P:---- X:---- Z:---- V:---- E:---- PredLog.sat_concatMap_retains_missing_step P:---- X:---- Z:---- V:---- E:---- PredLog.sat_flattenAnd_cf_missing_step P:---- X:---- Z:---- V:---- E:---- PredLog.sat_flattenAnd_retains_missing_step P:---- X:---- Z:---- V:---- E: Recursion.sat_qfac_cf_broken_step P:---- X:---- Z:---- V:---- E:---- Recursion.sat_rev_cf_broken_step P:---- X:---- Z:---- V:---- E:---- Risers.big_sat_risersBy_nonEmpty_broken2_step P:---- X:---- Z:---- V:---- E:---- Risers.big_sat_risersBy_nonEmpty_broken_step P:---- X:---- Z:---- V:---- E:---- Risers.sat_risers_broken2_step P:---- X:---- Z:---- V:---- E:---- Risers.sat_risers_broken3_step P:---- X:---- Z:---- V:---- E:---- Risers.sat_risers_broken_step P:---- X:---- Z:---- V:---- E:---- Risers.sat_risers_missing_le_step P:---- X:---- Z:---- V:---- E:---- Shrink.big_sat_shrink_lazy_step P:---- X:---- Z:---- V:---- E:---- Timeouts … We now know why, and how to address this: stay tuned

20
Whats next: usability Proving is reasonably fast, now explore: Automatic strengthening of induction hypotheses Pretty printing models as counterexamples More induction principles Testing in larger scale Interfacing with theorem provers for manual proofs? 20 Lots of man-hours needed, come help please!

21
Related work Liquid Types [Jhala et al] Predicate abstraction Inference Quantifiers driven by type system ESC/Haskell [Xu et al] Contracts are programs Symbolic execution/inlining Zeno [Sonnex et al] Automated equality proofs Clever heuristics Strict semantics Catch [Mitchell] Pattern match errors Via dataflow analysis Dafny & Boogie [Leino et al], ACL2 Leon [Suter et al] Specialized decision procedure for FP Good for first-order F7/F* [Swamy et al] Hoare logic for FP [Regis-Gianas & Pottier] HO logics CBV *really* helps HO model checking, MoChi [Kobayashi et al] Specialized decision procedures Lots of techniques stacked Good for inference, good for counterexamples Symbolic execution-based [ Tobin- Hochstadt and Van Horn][Xu] Abstraction, lots of smaller queries to theorem prover HOLCF-based verification [Huffman] Reasoning in a very rich logic that contains formalization of a domain theory More sophisticated axiomatization, ability to reason about parametricity and monad laws

22
What we did and what I learnt Weve given a semantic basis for the verification of Haskell programs We demonstrated that it is implementable 22 We can verify FP in a simple and robust way: For this particular case a simple solution seems to do the job. It appears affordable to use a very precise abstraction of your program and trust your 2013 theorem proving technology Thank you for your attention!

Similar presentations

© 2017 SlidePlayer.com Inc.

All rights reserved.

Ads by Google