(*
** 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: June, 2009
//

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

// some examples translated from in Chapter 5 in the textbook

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

#include "BUCASCS320.hats"

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

// textbook, page 192

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

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

exception Empty of ()
exception Subscript of ()

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

// textbook, page 192

fun{a:t@ype} hd (xs: seq a): a = case+ xs of
  | Cons (x, _) => x | Nil () => $raise Empty ()
// end of [hd]

fun{a:t@ype} tl (xs: seq a): seq a = case+ xs of
  | Cons (_, fxs) => fxs () | Nil () => $raise Empty ()
// end of [hd]

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

// textbook, page 192

fun{a:t@ype} cons (x: a , xs: seq a): seq a = Cons (x, lam () => xs) 

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

// textbook, page 193

fun from (k: int): seq int = Cons (k, lam () => from (k+1)) 

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

// textbook, page 193

fun{a:t@ype} take (xs: seq a, n: int): list0 a =
  if n = 0 then list0_nil ()
  else begin case+ xs of // n <> 0
  | Nil () => $raise Subscript ()
  | Cons (x, fxs) => list0_cons (x, take (fxs (), n-1))
  end // end of [if]
// end of [take]

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

fun{a:t@ype} nth (xs: seq a, n: int): a = case+ xs of
  | Cons (x, fxs) => if n = 0 then x else nth (fxs (), n-1)
  | Nil () => $raise Subscript ()
// end of [nth]

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

// textbook, page 195

fun{a,b:t@ype} map
  (xs: seq a, f: a -<cloref1> b): seq b = case+ xs of
  | Cons (x, fxs) => Cons (f x, lam () => map (fxs (), f)) 
  | Nil () => Nil ()
// end of [map]

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

// textbook, page 196

fun{a:t@ype} filter (pred: a -<cloref1> bool, xs: seq a): seq a =
  case+ xs of
  | Cons (x, fxs) => begin
      if pred x then Cons (x, lam () => filter (pred, fxs ())) else filter (pred, fxs ())
    end // end of [Cons]  
  | Nil () => Nil ()
// end of [filter]

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

fun sift (p: int, xs: seq int): seq int =
  filter<int> (lam (x) => x mod p <> 0, xs)
// end of [sift]

fun sieve (xs: seq int): seq int = let
  val- Cons (x, fxs) = xs in Cons (x, lam () => sieve (sift (x, fxs ())))
end (* end of [sieve] *)

val primes = sieve (from 2)

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

val p5000 = nth (primes, 5000-1)
val () = printf ("p5000 = %i", @(p5000))
val () = print_newline ()
val () = print ("Testing memoization: a long pause shoule be experienced!")
val () = print_newline ()
val p5000 = nth (primes, 5000-1)
val () = printf ("p5000 = %i", @(p5000))
val () = print_newline ()

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

implement main () = ()

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

(* end of [chapater5_examples.dats] *)