```(*
** Course: Concepts of Programming Languages (BU CAS CS 320)
** Semester: Summer I, 2009
** Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
*)

//
// Author: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
// Time: Wednesday, June 11, 2009
//

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

#include "BUCASCS320.hats"

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

// a datatype for streams (no memoization)

datatype seq (a:t@ype) =
Nil(a) of () | Cons(a) of (a, () -<cloref1> seq a)

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

typedef int2 = @(int, int)

fun from2_one (i: int, j: int): seq (int2) =
Cons ( @(i, j), lam () => from2_one (i, j+1) )
// end of [from2_one]

fun{a:t@ype} seq_interleave
(xs1: seq a, xs2: seq a): seq a = case+ xs1 of
| Cons (x1, fxs1) => Cons (x1, lam () => seq_interleave (xs2, fxs1 ()))
| Nil () => xs2
// end of [seq_interleave]

fun{a:t@ype} seq_merge
(xs1: seq a, xs2: seq a, lte: (a, a) -<cloref1> bool): seq a =
case+ xs1 of
| Cons (x1, fxs1) => begin case+ xs2 of
| Cons (x2, fxs2) => begin
if x1 \lte x2 then Cons (x1, lam () => seq_merge (fxs1 (), xs2, lte))
else Cons (x2, lam () => seq_merge (xs1, fxs2 (), lte))
end // end of [Cons]
| Nil () => xs1
end // end of [Cons]
| Nil () => xs2
// end of [seq_merge]

fun lte_int2_int2
(xy1: int2, xy2: int2): bool = let
val s1 = xy1.0 + xy1.1; val s2 = xy2.0 + xy2.1
in
s1 < s2 orelse (s1 <= s2 andalso xy1.0 <= xy2.0)
end (* end of [lte_int2_int2] *)

fun from2_all
(i: int, j: int) = let
val ij = @(i, j)
in
Cons (ij
, lam () => let
val fstrow = from2_one (i, j+1)
val restbl = from2_all (i+1, j)
in
seq_merge<int2> (restbl, fstrow, lam (xy1, xy2) => xy1 \lte_int2_int2 xy2)
end (* end of [lam] *)
) // end of [Cons]
end // end of [from2_all]

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

val theNat2Seq = from2_all (0, 0) // a list of all pairs of natural numbers

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

val () = loop (theNat2Seq, 20) where {
fun loop (xys: seq int2, n: int): void =
if n > 0 then let
val- Cons (xy, fxys) = xys
val () = printf ("x = %i and y = %i\n", @(xy.0, xy.1))
in
loop (fxys (), n-1)
end // end of [if]
// end of [loop]
} // end of [val]

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

implement main () = ()

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

(* end of [code-2009-06-11.dats] *)
```