typedef nat_f =
{X:type} (X -<cloref> X) -<cloref> X -<cloref> X
fn pair_get_fst {X,Y:type} '(x: X, _: Y):<> X = x
fn pair_get_snd {X,Y:type} '(_: X, y: Y):<> Y = y
typedef int = uintptr
val _0 = uintptr_of_uint (0U)
val _1 = uintptr_of_uint (1U)
#define isucc succ_uintptr
fun print_nat_f (n: nat_f): void = print (n {int} (lam x => isucc x) (_0))
val Z = (lam s => lam z => z): nat_f
val S = lam (n: nat_f): nat_f =<cloref> lam s => lam z => n(s)(s(z))
val zero = Z
val one = S(zero)
val two = S(one)
val three = S(two)
val four = S(three)
val five = S(four)
fn add (m: nat_f, n: nat_f):<> nat_f = m (S) (n)
fn mul (m: nat_f, n: nat_f):<> nat_f = m {nat_f} (n S) (Z)
fn pow (m: nat_f, n: nat_f):<> nat_f = n {nat_f-<cloref>nat_f} (m {nat_f}) (S) (Z)
val () = begin
print_string "pow (3, 5) = ";
print_nat_f (pow (three, five));
print_newline ()
end
fn pred (n: nat_f):<> nat_f = let
val z = '(zero, zero)
val s = lam '(n1: nat_f, n2: nat_f): '(nat_f, nat_f) =<cloref> '(S n1, n1)
val '(_, res) = n {'(nat_f, nat_f)} s z
in
res
end
fn fact (n: nat_f):<> nat_f = let
typedef X = '(nat_f, nat_f)
val z: X = '(one, one)
val s = lam ('(x, y): X): X =<cloref> '(S x, mul (x, y))
in
pair_get_snd (n {X} (s) (z))
end
val () = begin
print_string "fact (5) = ";
print_nat_f (fact five);
print_newline ()
end
fun fib (n: nat_f): nat_f =
let
typedef X = '(nat_f, nat_f)
val z: X = '(zero, one)
val s = lam ('(x, y): X): X =<cloref> '(y, add (x, y))
in
pair_get_fst (n {X} (s) (z))
end
val _ = begin
print_string "fib (10) = ";
print_nat_f (fib (add (five, five)));
print_newline ()
end
fn ack
(m: nat_f):<> nat_f -<cloref> nat_f =
let
val helper =
lam (f: nat_f -<cloref> nat_f) =<cloref>
lam (n: nat_f): nat_f =<cloref> f (n {nat_f} (f) (one))
in
m {nat_f -<cloref> nat_f} helper (S)
end
val () = begin
print_string "ack (3, 5) = ";
print_nat_f (ack three five);
print_newline ()
end
typedef list_f (A: type) =
{X:type} (X, (A, X) -<cloref1> X) -<cloref1> X
val Nil = lam {A:type}: list_f (A) => lam (n, c) => n
val Cons =
lam {A:type} (x: A, xs: list_f A): list_f A =<cloref> lam (n, c) => c (x, xs (n, c))
val list_length =
lam {A:type} (xs: list_f A): int => let
val nil = _0
val cons = lam (_: A, i: int): int =<cloref> succ i
in
xs {int} (nil, cons)
end
val list_append =
lam {A:type} (xs: list_f A, ys: list_f A): list_f A => xs {list_f A} (ys, Cons{A})
val list_reverse =
lam {A:type} (xs: list_f A): list_f A => let
val nil = Nil {A}
val cons =
lam (x: A, xs: list_f A): list_f A =<cloref1> list_append (xs, Cons (x, Nil))
in
xs {list_f A} (nil, cons)
end
#define :: cons
#define ipred pred_uintptr
fun gen_list_f (i: Nat): list_f (int) =
if i = 0 then Nil else Cons (uintptr_of_int1 i, gen_list_f (i - 1))
typedef intlst = list0 int
fun print_intlist (xs: intlst): void =
case xs of
| list0_nil () => print_newline ()
| list0_cons (x, xs) => print_intlist_aux (x, xs)
and print_intlist_aux (x: int, xs: intlst): void =
case xs of
| list0_nil () => (print x; print_newline ())
| list0_cons (x', xs') => (print x; print_string ", "; print_intlist_aux (x', xs'))
fn print_list
(xs: list_f int): void = let
val nil = list0_nil ()
val cons = lam (x: int, xs: intlst): intlst =<cloref> list0_cons (x, xs)
in
print_intlist (xs {intlst} (nil, cons))
end
val () = let
val xs = gen_list_f (5)
val xs' = list_reverse xs
val xsxs = list_append (xs, xs)
val xsxs' = list_reverse xsxs
in
print_string "xs = ";
print_list xs;
print_string "length (xs) = ";
print (list_length xs);
print_newline ();
print_string "xs' = ";
print_list xs';
print_string "list_length (xs') = ";
print (list_length xs');
print_newline ();
print_string "xsxs = ";
print_list xsxs;
print_string "length (xsxs) = ";
print (list_length xsxs);
print_newline ();
print_string "xsxs' = ";
print_list xsxs';
print_string "length (xsxs') = ";
print (list_length xsxs');
print_newline ()
end
typedef gtree (A: type) =
{X:type} (X, (A -<cloref> X) -<cloref> X) -<cloref> X
val E = lam {A:type}: gtree (A) => lam (e, b) => e
val B = lam {A:type}
(f: A -<cloref> gtree A): gtree (A) =<cloref> lam (e, b) => b (lam x => f (x) (e, b))
typedef A = int
typedef btree = gtree (A)
fn print_btree
(t: btree): void = let
typedef X = () -<cloref1> void
val e = (lam () => print_string "E"): X
val b = lam (f: (A -<cloref> X)): X =<cloref>
lam () => begin print_string "B("; f (_0) (); print_string ", "; f (_1) (); print_string ")"
end
in
t {X} (e, b) ()
end
fn btree_size (t: btree):<> int = let
typedef X = int
val e = _0
val b = lam (f: (A -<cloref> X)): X =<cloref> isucc (f _1 + f _0)
in
t {X} (e, b)
end
fn btree_height (t: btree):<> int = let
typedef X = int
val e = _0
val b = lam (f: (A -<cloref> X)): X =<cloref> max (f _1, f _0) + _1
in
t {X} (e, b)
end
fn btree_isperfect (t: btree):<> bool = let
typedef X = Option int
val e = (Some _0): X
val b = lam (f: A -<cloref> X): X =<cloref>
case+ (f _0, f _1) of
| (Some h1, Some h2) =>
if h1 = h2 then Some (isucc h1) else None
| (_, _) => None
in
case+ t {X} (e, b) of None () => false | Some _ => true
end
fn btree_left
(t: btree):<> btree = let
typedef X = '(btree, btree)
val e = '(E, E): X
val b = lam
(f: (A -<cloref> X)): X =<cloref> let
val '(t1, _) = f (_1); val '(t2, _) = f (_0)
val f1 = lam (x: A): btree =<cloref> if x > _0 then t1 else t2
in
'(B {A} (f1), t2)
end in
pair_get_snd (t {X} (e, b))
end
fn btree_right
(t: btree):<> btree = let
typedef X = '(btree, btree)
val e = '(E, E): X
val b = lam
(f: (A -<cloref> X)): X =<cloref> let
val '(t1, _) = f (_1); val '(t2, _) = f (_0)
val f1 = lam (x: A): btree =<cloref> if x > _0 then t1 else t2
in
'(B {A} (f1), t1)
end in
pair_get_snd (t {X} (e, b))
end
val t0 = E: btree
val t1: btree = let
val f = lam (x: int): btree =<cloref> if x <= _0 then t0 else t0
in
B {A} (f)
end val t2: btree = let
val f = lam (x: int): btree =<cloref> if x <= _0 then t1 else t0
in
B {A} (f)
end
val () = begin
print_string "The tree t2 = "; print_btree t2; print_newline ()
end
val t3: btree = let
val f = lam (x: int): btree =<cloref> if x <= _0 then t1 else t2
in
B {A} (f)
end
val () = begin
print_string "The tree t3 = "; print_btree t3; print_newline ()
end
val isperfect = btree_isperfect (t1)
val () = (print "isperfect(t1) = "; print isperfect; print_newline ())
val isperfect = btree_isperfect (t3)
val () = (print "isperfect(t3) = "; print isperfect; print_newline ())
val t31: btree = btree_left (t3)
val t32: btree = btree_right (t3)
val () = begin
print_string "The left subtree of t3 = "; print_btree t31; print_newline ();
print_string "The right subtree of t3 = "; print_btree t32; print_newline ();
end
val s: int = btree_size (t3)
val h: int = btree_height (t3)
val () = begin
print_string "The size of t3 = "; print s; print_newline ();
print_string "The height of t3 = "; print h; print_newline ();
end
implement main () = ()