new example: random access lists

features polymorphic recursion, both in the logic and in programs
parent ac0cd54a
(** Random Access Lists.
The code below uses polymorphic recursion (both in the logic
and in the programs).
BUGS:
- induction_ty_lex has no effect on a goal involving polymorphic recursion
- a lemma function is not allowed to perform polymorphic recursion?
*)
module RandomAccessList
use import int.Int
use import int.ComputerDivision
use import list.List
use import list.Length
use import list.Nth
use import option.Option
type ral 'a =
| Empty
| Zero (ral ('a, 'a))
| One 'a (ral ('a, 'a))
function flatten (l: list ('a , 'a)) : list 'a
= match l with
| Nil -> Nil
| Cons (x, y) l1 -> Cons x (Cons y (flatten l1))
end
lemma length_flatten:
forall l: list ('a, 'a). length (flatten l) = 2 * length l
function elements (l: ral 'a) : list 'a
= match l with
| Empty -> Nil
| Zero l1 -> flatten (elements l1)
| One x l1 -> Cons x (flatten (elements l1))
end
let rec size (l: ral 'a) : int
variant { l }
ensures { result = length (elements l) }
=
match l with
| Empty -> 0
| Zero l1 -> 2 * size l1
| One _ l1 -> 1 + 2 * size l1
end
let rec add (x: 'a) (l: ral 'a) : ral 'a
variant { l }
ensures { elements result = Cons x (elements l) }
= match l with
| Empty -> One x Empty
| Zero l1 -> One x l1
| One y l1 -> Zero (add (x, y) l1)
end
let rec lemma nth_flatten (i: int) (l: list ('a, 'a))
requires { 0 <= i < length l }
variant { l }
ensures { match nth i l with
| None -> false
| Some (x0, x1) -> Some x0 = nth (2 * i) (flatten l) /\
Some x1 = nth (2 * i + 1) (flatten l) end }
= match l with
| Nil -> ()
| Cons _ r -> if i > 0 then nth_flatten (i-1) r
end
let rec get (i: int) (l: ral 'a) : 'a
requires { 0 <= i < length (elements l) }
variant { i, l }
ensures { nth i (elements l) = Some result }
= match l with
| Empty -> absurd
| One x l1 -> if i = 0 then x else get (i-1) (Zero l1)
| Zero l1 -> let (x0, x1) = get (div i 2) l1 in
if mod i 2 = 0 then x0 else x1
end
end
(* This file is generated by Why3's Coq driver *)
(* Beware! Only edit allowed sections below *)
Require Import BuiltIn.
Require BuiltIn.
Require int.Int.
Require int.Abs.
Require int.ComputerDivision.
Require list.List.
Require list.Length.
Require list.Nth.
Require option.Option.
(* Why3 assumption *)
Definition unit := unit.
Axiom qtmark : Type.
Parameter qtmark_WhyType : WhyType qtmark.
Existing Instance qtmark_WhyType.
(* Why3 assumption *)
Inductive ral
(a:Type) :=
| Empty : ral a
| Zero : (ral (a* a)%type) -> ral a
| One : a -> (ral (a* a)%type) -> ral a.
Axiom ral_WhyType : forall (a:Type) {a_WT:WhyType a}, WhyType (ral a).
Existing Instance ral_WhyType.
Implicit Arguments Empty [[a]].
Implicit Arguments Zero [[a]].
Implicit Arguments One [[a]].
(* Why3 assumption *)
Fixpoint flatten {a:Type} {a_WT:WhyType a} (l:(list (a*
a)%type)) {struct l}: (list a) :=
match l with
| Init.Datatypes.nil => Init.Datatypes.nil
| (Init.Datatypes.cons (x, y) l1) =>
(Init.Datatypes.cons x (Init.Datatypes.cons y (flatten l1)))
end.
(* Why3 goal *)
Theorem length_flatten : forall {a:Type} {a_WT:WhyType a},
forall (l:(list (a* a)%type)),
((list.Length.length (flatten l)) = (2%Z * (list.Length.length l))%Z).
intros a a_WT l.
induction l.
auto.
simpl (flatten (a0::l)).
destruct a0.
replace (Length.length ((a0,a1)::l))
with (1 + (Length.length l))%Z by auto.
unfold Length.length at 1; fold Length.length.
rewrite IHl.
ring.
Qed.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE why3session PUBLIC "-//Why3//proof session v5//EN"
"http://why3.lri.fr/why3session.dtd">
<why3session shape_version="4">
<prover id="0" name="Alt-Ergo" version="0.99.1" timelimit="6" memlimit="1000"/>
<prover id="1" name="CVC4" version="1.4" timelimit="6" memlimit="1000"/>
<prover id="5" name="Coq" version="8.4pl2" timelimit="6" memlimit="1000"/>
<prover id="6" name="CVC4" version="1.3" timelimit="1" memlimit="1000"/>
<file name="../random_access_list.mlw" expanded="true">
<theory name="RandomAccessList" sum="d4e729fc281cff0f1f6b9c21461a02b6" expanded="true">
<goal name="length_flatten" expanded="true">
<proof prover="5" edited="random_access_list_RandomAccessList_length_flatten_1.v"><result status="valid" time="0.83"/></proof>
</goal>
<goal name="WP_parameter size" expl="VC for size">
<proof prover="0"><result status="valid" time="0.02" steps="68"/></proof>
</goal>
<goal name="WP_parameter add" expl="VC for add">
<proof prover="0"><result status="valid" time="0.02" steps="70"/></proof>
</goal>
<goal name="WP_parameter nth_flatten" expl="VC for nth_flatten">
<transf name="split_goal_wp">
<goal name="WP_parameter nth_flatten.1" expl="1. postcondition">
<proof prover="0"><result status="valid" time="0.02" steps="11"/></proof>
</goal>
<goal name="WP_parameter nth_flatten.2" expl="2. variant decrease">
<proof prover="0"><result status="valid" time="0.02" steps="21"/></proof>
</goal>
<goal name="WP_parameter nth_flatten.3" expl="3. precondition">
<proof prover="0"><result status="valid" time="0.02" steps="12"/></proof>
</goal>
<goal name="WP_parameter nth_flatten.4" expl="4. postcondition">
<proof prover="6"><result status="valid" time="0.24"/></proof>
</goal>
<goal name="WP_parameter nth_flatten.5" expl="5. postcondition">
<proof prover="0"><result status="unknown" time="0.04"/></proof>
<proof prover="1"><result status="valid" time="0.07"/></proof>
</goal>
</transf>
</goal>
<goal name="WP_parameter get" expl="VC for get" expanded="true">
<proof prover="0"><result status="valid" time="0.34" steps="410"/></proof>
</goal>
</theory>
</file>
</why3session>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment