Abstract Data Types
General Properties
An abstract datatype is an encapsulation mechanism.
In general it is composed of several components
- A data structure or structures (often called the sorts)
- A set of operations (called the methods or operations).
- A precise description of the types of the methods (called a signature).
- A precise set of rules about how it behaves
(called the abstract specification or the axiomatic description).
- An implementation hidden from the programmer who uses the data type.
It allows programmers
to hide the details of an implementation, and to implement
multiple different versions that might behave differently, especially
with respect to resources used.
An example
- A list based table mechanism.
- Constant time addition
- Linear time search
- A balanced tree based table mechanism
- Log time addition
- Log time search
In Haskell two features of the language are commonly used
to implement abstract data types.
- The class system
- The module system
Comparing Abstract Data Types with Algebraic Data Types.
Features of Algebraic Data Types
- Defined using "data" declartion in Haskell.
- Exposes the Constructors of the internal representation.
- Data is decomposed using pattern matching.
- Makes the programmers responsible for maintaining implementation invariants.
- Has only a single implementation.
- All internals of the implementation are visible to programmers who use the type.
Features of Abstract Data Types
- Implemented with the class system or module system in Haskell.
- Internal implementation details hidden from user.
Constructors are hidden and no pattern matching is available.
- Access to data type is through "methods" or "operators"
- The exact types of the "methods" or operators is exposed in a signature.
- Supports multiple implementations.
- Operational semantics is described by an axiomatic specification. All actual implementations
must meet the specification (behave correctly) but are free to choose any implementation.
Components of Abstract Data Types
Abtsratc data types are often described as having severaol components
- A data type or types
- A set of operations
- A specification
- A signature
- A set of axioms
- A set of implementation
Signatures
A Signature is a set of contracts (or types)
that the operation of the abstract data type must export
(i.e. provide implementations for). In some systems
the signature also includes axioms that all
implementations must obey.
Examples
- Stack
push :: a -> Stack a -> Stack a
top :: Stack a -> a
pop :: Stack a -> Stack a
emptyStack:: Stack a
empty :: Stack a -> Bool
- Queue
enQ :: a -> Queue a -> Queue a
deQ :: Queue a -> (a,Queue q)
emptyQ :: Queue a
isEmpty:: Queue a -> Bool
- Priority Queue
add :: a -> PQ a -> PQ a
min :: PQ a -> Maybe(a)
deletemin:: PQ a -> Maybe(PQ a)
emptyPQ :: PQ a -> Bool
- Numbers
(+):: Num t => t -> t -> t
(*):: Num t => t -> t -> t
0:: Num t -> t
etc.
Implementing using the class system is done through class and instance
declarations.
class Stacklike t where
push :: a -> t a -> t a
top :: t a -> a
pop :: t a -> t a
emptyStack:: t a
empty :: t a -> Bool
|
Every instance is a separate implementation.
instance Stacklike [] where
push x xs = x :xs
top (x:xs) = x
pop (x:xs) = xs
emptyStack = []
empty [] = True
empty (x:xs) = False
|
Implementing using the module system is done through manipulating
what information is exported from a file.
module Stack(Stack(),push,top,pop,emptyStack,empty) where
data Stack a = EmptyStack | Push a (Stack a)
push :: a -> Stack a -> Stack a
push x xs = Push x xs
top :: Stack a -> a
top (Push x xs) = x
pop :: Stack a -> Stack a
pop (Push x xs) = xs
emptyStack:: Stack a
emptyStack = EmptyStack
empty :: Stack a -> Bool
empty = EmptyStack
|
The Stack() means that the the type Stack is exported, but the constructors
are not exported.
Algebraic Specification
An algebraic specification describes how an implementation should behave.
It is generally written as a set of equivalencies. I.e. equations that
state that two programs are equal. Normally equality between programs
is described in terms of observational equivalence.
Two programs are observational equivalent if there are no program
contexts that can distinguish them. A context is an additional
set of commands or expressions surrounding the programs.
In terms of abstract data types contexts are often described as a series of
calls to the operations or methods of the abstract type.
- In a pure implementation, observational equivalence means
two program fragments can be switched for one another and no
program could tell the difference.
- In a command based implementation, observational equivalence
usually means that the sequence of updates to variables is such that
for any starting set of values of the variables, the end set of values
is the same.
Some example axiomatic specifications follow:
Back to the Daily Record.
Back to the class web-page.