dataprop FACT (int, int) =
| FACTbas (0, 1) of ()
| {n:nat} {r,s:int}
FACTind (n+1, s) of (FACT (n, r), MUL (r, n+1, s))
prfun FACTistot
{n:nat} .<n>. (): [r:int] FACT (n, r) =
sif n > 0 then let
val pf1 = FACTistot () in FACTind {n-1} (pf1, mul_istot ())
end else FACTbas ()
prfun FACTisfun {n:nat} {r1,r2:int} .<n>.
(pf1: FACT (n, r1), pf2: FACT (n, r2)): [r1==r2] void =
sif n > 0 then let
prval FACTind (pf11, pf12) = pf1 and FACTind (pf21, pf22) = pf2
prval () = FACTisfun (pf11, pf21)
prval () = mul_isfun (pf12, pf22)
in
end else let
prval FACTbas () = pf1 and FACTbas () = pf2
in
end
dataprop FACT2 (int, int, int) =
| {r:int} FACT2bas (0, r, r) of ()
| {n:nat} {r0,r1,r2:int}
FACT2ind (n+1, r0, r2) of (MUL (n+1, r0, r1), FACT2 (n, r1, r2))
fun fact2 {n:nat} {r:int} .<n>.
(n: int n, r: int r):<> [s:int] (FACT2 (n, r, s) | int s) =
if n > 0 then let
val (pfmul | r1) = n imul2 r
val (pf1 | s) = fact2 (n-1, r1)
in
(FACT2ind (pfmul, pf1) | s)
end else (FACT2bas () | r)
prfun lemma {n:nat} {r,r1,r2:int} .<n>.
(pf1: FACT (n, r), pf2: FACT2 (n, r1, r2)): MUL (r, r1, r2) =
sif n > 0 then let
prval FACTind (pf1, pf1mul) = pf1 prval FACT2ind (pf2mul, pf2) = pf2 prval pf1res = lemma {n-1} (pf1, pf2) prval pfres = mul_istot {r,r1} ()
prval () = mul_associate (pf1mul, pf2mul, pfres, pf1res)
in
pfres
end else let
prval FACTbas () = pf1
prval FACT2bas () = pf2
prval pfres = mul_istot {1,r1} ()
prval () = mul_elim {1,r1} (pfres)
in
pfres
end
fun fact {n:nat} .<>.
(n: int n):<> [s:int] (FACT (n, s) | int s) = let
val (pf1 | s) = fact2 (n, 1)
prval [s:int] pf2 = FACTistot {n} ()
prval pfmul = lemma (pf2, pf1)
prval () = mul_elim {s,1} (pfmul)
in
(pf2 | s)
end
implement
main () = () where {
#define N 10
val (pf | ans) = fact (N)
val () = printf ("mul(1 ... %i) = %i\n", @(N, ans))
}