//
//
// An example involving the datatype list0
//
//

staload _(*anonymous*) = "prelude/DATS/list.dats"
staload _(*anonymous*) = "prelude/DATS/list0.dats"

#define nil list0_nil
#define cons list0_cons
#define :: list0_cons

extern fun list0_cross_with {a,b,c:type}
  (xs: list0 a, ys: list0 b, f: (a, b) -> c, res: list0 c): list0 c

implement list0_cross_with {a,b,c} (xs, ys, f, res) = let
  fun loop1
    (x: a, ys: list0 b, res: list0 c):<cloref1> list0 c = case+ ys of
    | y :: ys => loop1 (x, ys, f (x, y) :: res)
    | nil () => res
  fun loop2 (xs: list0 a, res: list0 c):<cloref1> list0 c = case+ xs of
    | x :: xs => loop2 (xs, loop1 (x, ys, res))
    | nil () => res
in
  loop2 (xs, res)
end // end of [list0_cross_with]

(* ****** ****** *)

datatype bt = B of (bt, bt) | E of ()
typedef bts = list0 (bt)

extern fun bintree_list_gen (n: int): bts

implement bintree_list_gen (n) = case+ 0 of
  | _ when n > 0 => list0_reverse (loop (0, n-1, nil ())) where {
      fun loop (i: int, j: int, res: bts): bts =
        if j >= 0 then let
          val ts1 = bintree_list_gen (i) and ts2 = bintree_list_gen (j)
          val res = begin
            list0_cross_with {bt,bt,bt} (ts1, ts2, lam (t1, t2) => B (t1, t2), res)
          end
        in
          loop (i+1, j-1, res)
        end else begin
          res
        end // end of [if]
    } // end of [where]
  | _ => cons (E (), nil ())

(* ****** ****** *)

implement main () = let
  val ts1 = bintree_list_gen (1); val n1 = list0_length (ts1)
  val () = printf ("length(ts1) = %i\n", @(n1))
  val ts2 = bintree_list_gen (2); val n2 = list0_length (ts2)
  val () = printf ("length(ts2) = %i\n", @(n2))
  val ts3 = bintree_list_gen (3); val n3 = list0_length (ts3)
  val () = printf ("length(ts3) = %i\n", @(n3))
  val ts4 = bintree_list_gen (4); val n4 = list0_length (ts4)
  val () = printf ("length(ts4) = %i\n", @(n4))
  val ts5 = bintree_list_gen (5); val n5 = list0_length (ts5)
  val () = printf ("length(ts5) = %i\n", @(n5))
  val ts10 = bintree_list_gen (10); val n10 = list0_length (ts10)
  val () = printf ("length(ts10) = %i\n", @(n10))
in
  // empty
end // end of [main]

(* ****** ****** *)

(* end of [list0-2008-09-05.dats] *)