summaryrefslogtreecommitdiff
path: root/Test/hofs/Twice.dfy
blob: 5d948a58184fb87ef3bfb5ac14e8467ae6746ef5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// RUN: %dafny /print:"%t.print" "%s" > "%t"
// RUN: %diff "%s.expect" "%t"

function method Twice<A>(f : A -> A): A -> A
{
  x requires f.requires(x) && f.requires(f(x))
    reads f.reads(x) reads if f.requires(x) then f.reads(f(x)) else {}
  => f(f(x))
}

method Simple() {
  assert Twice(x => x + 1)(0) == 2;
  assert Twice(Twice(x => x + 1))(0) == 4;

  // why does these fail? need requires/reads for literals?
  // assert Twice(Twice)(x => x + 1)(0) == 4;
  // assert Twice(Twice)(Twice)(x => x + 1)(0) == 16;
}

method WithReads() {
  var a : array<int> := new int[1];
  a[0] := 1;
  var f := x reads a => x + a[0];
  assert Twice(f)(0) == 2;
  a[0] := 2;
  assert Twice(f)(0) == 4;
  assert Twice(f)(0) == 2; // should fail
  assert false;            // should fail
}


function method Twice_bad<A>(f : A -> A): A -> A
{
  x requires f.requires(x) && f.requires(f(x))
    reads f.reads(x) + f.reads(f(x))
  => f(f(x))
}