Reading material

Pages 193-198.

Additional material

(* finite and infinite sequences *)
datatype 'a seq = Nil
                | Cons of 'a * (unit -> 'a seq)

(* operations on sequences *)
signature SEQUENCE =
  sig

  (* returns the head of the sequence *)
  val hd : 'a seq -> 'a

  (* returns the tail of the sequence *)
  val tl : 'a seq -> 'a seq

  (* tests if the sequence is empty *)
  val null : 'a seq -> bool

  (* returns the sequence obtained by combining the head and the tail
     sequence *)
  val cons : 'a * 'a seq -> 'a seq

  (* returns the sequence consisting of the first n elements of the 
     sequence *)
  val take : 'a seq * int -> 'a seq

  (* returns the sequence obtained by dropping the first n elements
     of the sequence *)
  val drop : 'a seq * int -> 'a seq

  (* returns the sequence with the elements of the list *)
  val fromList : 'a list -> 'a seq

  (* returns the list with the elements of the sequence *)
  val toList : 'a seq -> 'a list

  (* returns the concatenation of the sequences *)
  val @ : 'a seq * 'a seq -> 'a seq

  (* returns the interleaving of the sequences *)
  val || : 'a seq * 'a seq -> 'a seq

  (* returns the sequence obtained by applying the function f to all its
     elements *)
  val map : ('a -> 'b) -> 'a seq -> 'b seq

  (* returns the sequence of all elements of the sequence which satisfy
     the predicate *)     
  val filter : ('a -> bool) -> 'a seq -> 'a seq

  (* returns the initial segment of the sequence which satisfies the
     predicate *)
  val takewhile : ('a -> bool) -> 'a seq -> 'a seq

  (* returns the sequence obtained by dropping the initial segment of 
     the sequence which satisfies the predicate *)
  val dropwhile : ('a -> bool) -> 'a seq -> 'a seq

  (* tests if there exists an element in the sequence which satisfies 
     the predicate *)
  val exists : ('a -> bool) -> 'a seq -> bool

  (* tests if all elements in the sequence satisfy the predicate *)
  val all : ('a -> bool) -> 'a seq -> bool

  (* given a function which associates to every element of the sequence 
     a string, prints the elements of the sequence *)
  val print : ('a -> string) -> 'a seq -> unit
  end

structure Sequence : SEQUENCE =
  struct

  fun hd (Cons(x, _)) = x
    | hd Nil          = raise Empty

  fun tl (Cons(_, xf)) = xf()
    | tl Nil           = raise Empty

  fun null Nil = true
    | null _   = false

  fun cons (x, xq) = Cons(x, fn () => xq)

  fun take (xq, 0)          = Nil
    | take (Nil, _)         = raise Subscript
    | take (Cons(x, xf), n) = Cons(x, fn () => take(xf(), n - 1))

  fun drop (xq, 0)          = xq
    | drop (Nil, _)         = raise Subscript
    | drop (Cons(x, xf), n) = drop(xf (), n - 1)

  fun fromList []        = Nil
    | fromList (x :: xs) = Cons(x, fn () => fromList xs)

  fun toList Nil           = []
    | toList (Cons(x, xf)) = x :: toList(xf())

  infix @
  fun (Nil           @ yq) = yq
    | ((Cons(x, xf)) @ yq) = Cons(x, fn () => (xf() @ yq))

  infix ||
  fun (Nil           || yq) = yq
    | ((Cons(x, xf)) || yq) = Cons(x, fn () => (yq || xf()))

  fun map f Nil           = Nil
    | map f (Cons(x, xf)) = Cons(f x, fn () => map f (xf()))

  fun filter pred Nil           = Nil
    | filter pred (Cons(x, xf)) =
        if pred x then Cons(x, fn () => filter pred (xf()))
        else filter pred (xf())

  fun takewhile pred Nil           = Nil
    | takewhile pred (Cons(x, xf)) =
        if pred x then Cons(x, fn () => takewhile pred (xf()))
        else Nil

  fun dropwhile pred Nil           = Nil
    | dropwhile pred (Cons(x, xf)) =
        if (pred x) then dropwhile pred (xf())
        else xf()

  fun exists pred Nil           = false
    | exists pred (Cons(x, xf)) = (pred x) orelse (exists pred (xf()))

  fun all pred Nil           = true
    | all pred (Cons(x, xf)) = (pred x) andalso (all pred (xf()))

  fun print toString Nil           = (TextIO.print "\n"; ())
    | print toString (Cons(x, xf)) = (TextIO.print(toString(x)); print toString (xf()))

  end