This preview shows pages 1–3. Sign up to view the full content.
CS 3110 Recitation 7
Functional stacks and queues, dictionaries,
fractions
Functional data structures
In this recitation, we look at examples of structures and signatures that implement data structures. We show
that stacks and queues can be implemented efficiently in a functional style.
What is a functional stack, or a functional queue? It is a data structure for which the operations do not
change
the data structure, but rather create a new data structure, with the appropriate modifications, instead
of changing it inplace. In imperative languages, data operations generally support
destructive update
—
“destructive” in the sense that after the update is done, the original data structure is gone. Functional
abstractions support
nondestructive updates
: the original value is still around, unmodified, so code that was
using it is unaffected. For efficiency, it is important to implement nondestructive updates not by creating an
entirely new data structure, but by sharing as much as possible with the original data structure.
Stacks
Recall a stack: a lastin firstout (LIFO) queue. Just like lists, the stack operations fundamentally do not care
about the type of the values stored, so it is a naturally polymorphic data structure.
Here is a possible signature for functional stacks:
module type STACK =
sig
(* A stack of elements of type 'a. We write
to
* denote a stack whose top element is a1, with successive
* elements a2, a3,.
..an. *)
type 'a stack
exception EmptyStack
(* The empty stack. *)
val empty : 'a stack
(* Whether this stack is empty. *)
val isEmpty : 'a stack > bool
(* Returns a new stack with x pushed onto the top. *)
val push : ('a * 'a stack) > 'a stack
(* Returns a new stack with the top element popped off. *)
val pop : 'a stack > 'a stack
(* The top element of the stack. *)
val top : 'a stack > 'a
(* map(f) maps one stack into a corresponding stack, using f. *)
val map : ('a > 'b) > 'a stack > 'b stack
This preview has intentionally blurred sections. Sign up to view the full version.
View Full Document (* app(f) applies f to every element of the stack, from the top down. *)
val app :
('a > unit) > 'a stack > unit
end
This signature specifies a parameterized abstract type for stack. Notice the type variable 'a. The signature also
specifies the empty stack value, and functions to check if a stack is empty, and to perform push, pop and top
operations on the stack. Moreover, we specify functions map and app to walk over the values of the stack.
We also declare an exception EmptyStack to be raised by top and pop operations when the stack is empty.
Here is the simplest implementation of stacks that matches the above signature. It is implemented in terms of
lists.
module Stack : STACK =
struct
type 'a stack = 'a list
exception EmptyStack
let empty : 'a stack = []
let isEmpty (l:'a list): bool =
(match l with
[] > true
 _ > false)
let push ((x:'a), (l:'a stack)):'a stack = x::l
let pop (l:'a stack):'a stack =
(match l with
[] > raise EmptyStack
 (x::xs) > xs)
let top (l:'a stack):'a =
(match l with
[] > raise EmptyStack
 (x::xs) > x)
This is the end of the preview. Sign up
to
access the rest of the document.
This note was uploaded on 10/25/2009 for the course PHYS 2214 at Cornell University (Engineering School).
 '07
 GIAMBATTISTA,A

Click to edit the document details