From 3fdaa8a4562929f0202c582699d574f1a7beefac Mon Sep 17 00:00:00 2001 From: leino Date: Fri, 1 Apr 2016 14:37:01 -0700 Subject: New test case, proving monad laws for lists --- Test/dafny4/MonadicLaws.dfy | 100 +++++++++++++++++++++++++++++++++++++ Test/dafny4/MonadicLaws.dfy.expect | 2 + 2 files changed, 102 insertions(+) create mode 100644 Test/dafny4/MonadicLaws.dfy create mode 100644 Test/dafny4/MonadicLaws.dfy.expect diff --git a/Test/dafny4/MonadicLaws.dfy b/Test/dafny4/MonadicLaws.dfy new file mode 100644 index 00000000..b668ffb8 --- /dev/null +++ b/Test/dafny4/MonadicLaws.dfy @@ -0,0 +1,100 @@ +// RUN: %dafny /compile:0 /rprint:"%t.rprint" /autoTriggers:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +// Monadic Laws +// Niki Vazou and Rustan Leino +// 28 March 2016 + +datatype List = Nil | Cons(head: T, tail: List) + +predicate Total(p: T -> U) + reads p.reads +{ + forall x :: p.reads(x) == {} && p.requires(x) +} + +function append(xs: List, ys: List): List +{ + match xs + case Nil => ys + case Cons(x, xs') => Cons(x, append(xs', ys)) +} + +lemma AppendNil(xs: List) + ensures append(xs, Nil) == xs +{ +} + +lemma AppendAssoc(xs: List, ys: List, zs: List) + ensures append(append(xs, ys), zs) == append(xs, append(ys, zs)); +{ +} + +function Return(a: T): List +{ + Cons(a, Nil) +} + +function Bind(xs: List, f: T -> List): List + requires Total(f) +{ + match xs + case Nil => Nil + case Cons(x, xs') => append(f(x), Bind(xs', f)) +} + +lemma LeftIdentity(a: T, f: T -> List) + requires Total(f) + ensures Bind(Return(a), f) == f(a) +{ + AppendNil(f(a)); +} + +lemma RightIdentity(m: List) + ensures Bind(m, Return) == m +{ + match m + case Nil => + assert Bind(Nil, Return) == Nil; + case Cons(x, m') => + calc { + Bind(Cons(x, m'), Return); + append(Return(x), Bind(m', Return)); + Cons(x, Bind(m', Return)); + } +} + +lemma Associativity(m: List, f: T -> List, g: T -> List) + requires Total(f) && Total(g) + ensures Bind(Bind(m, f), g) == Bind(m, x => Bind(f(x), g)) +{ + match m + case Nil => + assert Bind(m, x => Bind(f(x), g)) == Nil; + case Cons(x, xs) => + match f(x) + case Nil => + calc { + Bind(xs, y => Bind(f(y), g)); + Bind(Cons(x, xs), y => Bind(f(y), g)); + } + case Cons(y, ys) => + calc { + append(g(y), Bind(append(ys, Bind(xs, f)), g)); + { BindOverAppend(ys, Bind(xs, f), g); } + append(g(y), append(Bind(ys, g), Bind(Bind(xs, f), g))); + { AppendAssoc(g(y), Bind(ys, g), Bind(Bind(xs, f), g)); } + append(append(g(y), Bind(ys, g)), Bind(Bind(xs, f), g)); + Bind(Cons(x, xs), z => Bind(f(z), g)); + } +} + +lemma BindOverAppend(xs: List, ys: List, g: T -> List) + requires Total(g) + ensures Bind(append(xs, ys), g) == append(Bind(xs, g), Bind(ys, g)) +{ + match xs + case Nil => + case Cons(x, xs') => + AppendAssoc(g(x), Bind(xs', g), Bind(ys, g)); +} diff --git a/Test/dafny4/MonadicLaws.dfy.expect b/Test/dafny4/MonadicLaws.dfy.expect new file mode 100644 index 00000000..d903c7c5 --- /dev/null +++ b/Test/dafny4/MonadicLaws.dfy.expect @@ -0,0 +1,2 @@ + +Dafny program verifier finished with 16 verified, 0 errors -- cgit v1.2.3