(* Lecture 5: Tail Recursion, Structural Induction *) (* Author: Frank Pfenning *) (* Some material from Lecture 4 *) datatype suit = Clubs | Spades | Hearts | Diamonds datatype rank = Seven | Eight | Nine | Ten | Jack | Queen | King | Ace; datatype card = Card of suit * rank; (* Instead of datatype hand = Empty | Hold of card * hand; we use the built-in type 'a list datatype 'a list = nil | :: of 'a * 'a list; infixr ::; *) type hand = card list (* val filter : ('a -> bool) -> 'a list -> 'a list *) (* filter p l = sublist containing the elements of l for which p holds *) fun filter p nil = nil | filter p (x::l) = if p(x) then x::filter p l else filter p l; (* A tail-recursive alternative which uses local definitions *) (* Note that p is visible in filter2 and not passed as an argument *) fun filter p l = let fun filter2 (nil,k) = k | filter2 (x::l,k) = if p(x) then filter2(l,x::k) else filter2(l,k) in filter2 (l,nil) end (* collectSuit (s:suit, h:hand) = hand consisting of cards in h of suit s *) fun collectSuit (s:suit, h:hand):hand = filter (fn (Card(s',h)) => s = s') h; (* val range : int * int -> int *) fun range (m,n) = if m > n then nil else m::range(m+1,n); (* val rev2 : 'a list * 'a list -> 'a list *) (* rev2 (l,k) reverses l by accumulating the reverse in k *) fun rev2 (nil, k) = k | rev2 (x::l, k) = rev2 (l, x::k); (* val rev : 'a list -> 'a list reverses a list *) fun rev (l) = rev2 (l,nil); (* val pairList : 'a list * 'b list -> ('a * 'b) list *) (* pairList (l,k) creates a list of pairs from a pair of lists *) (* raises General.Domain if lists are of unequal length *) fun pairList (nil,nil) = nil | pairList (x::l,y::k) = (x,y)::pairList(l,k) | pairList _ = raise General.Domain; (* val append : 'a list * 'a list -> 'a list *) (* appends two lists, written as l @ k in the Standard Basis *) fun append (nil, k) = k | append (x::l, k) = x::append(l,k);