dataprop TALLY (int, int) =
| TALLYbas (0, 0) of ()
| {n:nat} {s:int}
TALLYind (n+1, s+n+1) of TALLY (n, s)
prfun TALLYistot
{n:nat} .<n>. (): [r:int] TALLY (n, r) =
sif n > 0 then TALLYind (TALLYistot {n-1} ()) else TALLYbas ()
prfun TALLYisfun {n:nat} {r1,r2:int} .<n>.
(pf1: TALLY (n, r1), pf2: TALLY (n, r2)): [r1==r2] void =
sif n > 0 then let
prval TALLYind pf1 = pf1 and TALLYind pf2 = pf2
in
TALLYisfun (pf1, pf2)
end else let
prval TALLYbas () = pf1 and TALLYbas () = pf2
in
end
prfun lemma {n:nat} {s,p:int} .<n>.
(pf1: TALLY (n, s), pf2: MUL (n, n+1, p)): [2*s == p] void =
sif n == 0 then let
prval TALLYbas () = pf1 and MULbas () = pf2
in
end else let prval TALLYind (pf1) = pf1 prval pf2 = mul_commute (pf2) prval MULind (pf2) = pf2 prval MULind (pf2) = pf2 prval () = lemma (pf1, pf2) in
end
fun tally3 {n:nat} .<>. (n: int n)
:<> [s:int] (TALLY (n, s) | int (s)) = let
prval pf1 = TALLYistot ()
val (pf2 | p) = n imul2 (n+1)
prval () = lemma (pf1, pf2)
in
(pf1 | p / 2)
end
implement
main () = () where {
#define N 100
val (pf | ans) = tally3 (N)
val () = printf ("sum(1 ... %i) = %i\n", @(N, ans))
}