datatype Colour = Red | White | Blue
datatype Nat = Zero | Succ(n: Nat)
Zero
, Succ(Zero)
,
Succ(Succ(Zero))
, etc.Zero < Succ(Zero) < Succ(Succ(Zero))
function add(n1: Nat, n2: Nat): Nat
{
match n1
case Zero => n2
case Succ(n) => Succ(add(n, n2))
}
lemma add_unit(n: Nat)
ensures add(n, Zero) == n
ensures add(Zero, n) == n
{}
lemma add_succ(n1: Nat, n2: Nat)
ensures Succ(add(n1,n2)) == add(n1, Succ(n2))
{}
{}
,
then it's an axiom (i.e., we assume it to
be true).
lemma add_commutative(n1: Nat, n2: Nat)
ensures add(n1, n2) == add(n2, n1)
{}
lemma {:induction n1} add_commutative(n1: Nat, n2: Nat)
ensures add(n1, n2) == add(n2, n1)
{
match n1
case Zero =>
calc {
add(Zero, n2);
== // def. add
n2;
== { add_unit(n2); }
add(n2, Zero);
}
case Succ(n) =>
// Inductive hypothesis: add(n, n2) == add(n2, n)
}
case Succ(n) =>
// Inductive hypothesis: add(n, n2) == add(n2, n)
calc {
add(n1, n2);
== // n1 == Succ(n)
add(Succ(n), n2);
== // def. add
Succ(add(n,n2));
== // IH: add(n, n2) == add(n2, n)
Succ(add(n2,n));
== { add_succ(n2, n); }
add(n2, Succ(n));
== // Succ(n) == n1
add(n2, n1);
}
Activity: Let's define together a functional library to manipulate Lists.
datatype List = ...
datatype List = Nil | Cons (head: T, tail: List)
List
, we prove:
lemma reverse_append<T>(l1: List<T>, l2: List<T>)
ensures reverse(append(l1, l2)) ==
append(reverse(l2), reverse(l1))
Nil
reverse(append(Nil, l2)) == append(reverse(l2), reverse(Nil))
Cons(h,x)
reverse(append(Cons(h,x), l2)) ==
append(reverse(l2), reverse(Cons(h,x)))
x
reverse(append(x, l2)) == append(reverse(l2), reverse(x))
Consider the following C# code:
using System.Numerics;
namespace _module
{
public partial class SoftSpecExample
{
public static void sum2(BigInteger x,
BigInteger y,
out BigInteger r)
{
r = x + y;
}
}
}
We can create a trusted interface in Dafny:
class SoftSpecExample
{
static method {:extern} sum2(x: int, y: int) returns (r: int)
requires 0 <= x <= y
ensures r == x + y
}
{:extern}
attribute means that the
implementation is defined externally.We can now interact with the method sum2
:
include "sumInterface.dfy"
method Main()
{
var x := SoftSpecExample.sum2(20, 30);
assert x == 50;
print "Sum: ", x, "\n";
}
dafny sum.dfy sumNative.cs
Let's use the files provided with Project 2 to write a program that executes the verified "Dutch Flag algorithm" with a string of letters received as command-line argument.
Example:
./dsort.exe RWBBBWWRWRWBWRWRW
RRRRRWWWWWWWWBBBB