Table of Contents

Abstract Datatypes (ADT)

A tentative definition

In mathematics, algebraic structures consist of a (carrier) set (say - the natural numbers) as well as operations on elements of the set, satisfying specific axioms (e.g. commutativity for addition).

Very similar to algebraic structures, an abstract data type consists of:

The ADT List

In what follows, we define the ADT for lists and use it to exemplify the main ingredients of an ADT construction. The intuition (and subtlety) underlying ADTs is related to the duality between abstract and concrete representation.

This duality can also be found in logic. Consider the following formula:

$ \lnot p \wedge q $

The formula combines the (abstract) propositions into a logical (abstract) statement. We can know the truth value of this statement only under a (concrete) interpretation of the propositions $ p$ and $ q$ .

However, what makes the formula abstract is that its truth value is unconditioned by the meaning assigned to $ p$ and $ q$ . Thus:

Following this example, we find that:

We will make this intuition more precise in what follows.

Sorts

A sort is a symbol which is interpreted as a set. As illustrated above, sorts are abstract, while their interpretations, i.e. sets - are concrete.

We will produce a definition of the ADT list which is parametric with respect to the elements contained by the list. Hence, we require two sorts:

Base constructors

The base constructors for our ADT are:

$ Void : List$

$ Cons : E \times List \rightarrow List$

$ Void$ is the abstract representation of the empty list, while $ Cons$ is a operator which takes an element and a list and constructs a new list. This pair of constructors has the following properties:

In general, the properties of base constructors are more interesting and receive a more elaborate study which is outside the scope of this lecture. In the general case, deciding that a set of constructors are base constructors is non-trivial, however, for our examples it is straightforward. We do not elaborate on this otherwise interesting aspect.

ADT operators

The operations which we perform on lists are:

$ isEmpty : List \rightarrow \mathbb{B}$

$ size : List \rightarrow \mathbb{N}$

$ head : List \rightarrow E$

$ tail : List \rightarrow List$

$ append : List \times List \rightarrow List$

$ reverse : List \rightarrow List$

Their definitions are self-explanatory. We simply observe that we introduce and utilise the sorts of $ \mathbb{B}$ $ \mathbb{N}$ which are interpreted at the set of booleans and natural numbers respectively, with their corresponding standard operations.

Axioms

The operations defined above need additional specification to ensure that they behave in the desired way. Such a specification should express list manipulations/transformation in terms of the base constructors. For instance:

(H) and (T) are axioms, and describe the intended behaviour of the operations. Recall our two implementations LinkedList and ArrayList together with the functions Cons, head, tail. Note that the functions head and tail for both list implementations satisfy the above axioms.

We continue with:

Next, we move on to specify concatenation. We find that several axioms make sense:

While each of the above axioms describes sensible concatenation behaviour, the interesting questions are:

The first question is of rather philosophical nature, and depends on the specifier (programmer) intention. We shall not comment on that, however it is possible (using instruments from Category Theory) to study the question more formally and in more detail.

The answer to the second question is: no. As it turns out, it is sufficient to choose as axioms:

We shall see in the next lecture that, by taking these axioms for concatenation, we get (1),(3),(4) for free - they are direct consequences of the axioms.

There are several hints to why (A1) and (A2) are good axiom choices:

Which of the following are appropriate axioms for reversal?

Conclusion: The ADT List

An abstract datatype consists of:

A concrete datatype which implements and ADT must:

It is sometimes the case that axioms can also serve the role of implementations by themselves. Recall our LinkedList implementation of the ADT list. We have (at least) two possible ways to implement concatenation:

List append(List l1, List l2) {
   if (isEmpty(l1))
      return l2;
   List l = l1;
   while (!isEmpty(l1->next)){
      l1 = l1->next;
   }
   l1->next = l2;
   return l;
}

as well as:

List append(List l1, List l2) {
   if (isEmpty(l1))
      return l2;
   return cons(head(l1),append(tail(l1),l2));
}

The observation here is that Abstract Datatypes can serve as a programming model just like, for instance, Object-Oriented Programming.

The ADT FIFO

The data type FIFO (First-In First-Out) is given by the following base constructors:

and operators:

we omit other basic operators which are similar to those for lists, and focus our attention on defining axioms for $ Dequeue$ : the first inserted element must be removed:

attempting a dequeue operation on a FIFO of size larger than 1 will not affect the element which was introduced last:

FIFO implementation

There are multiple possible FIFO implementations, but here we focus on one which is itself abstract. It relies on seeing a FIFO as two lists denoted $ \langle l,r\rangle$ :

For brevity, we shall use the following notational conventions:

Let us consider the FIFO represented by: $ \langle 1:2:Void, 9:8:Void\rangle$ . A $ Enqueue$ of $ 0$ will produce the FIFO $ \langle 0:1:2:Void, 9:8:Void\rangle$ , while a $ Dequeue$ will produce $ \langle 1:2:Void, 8:Void\rangle$ . Finally, the elements of the FIFO, in the order in which they were introduced, are: $ 1,2,8,9$ .

The FIFO implementation has two issues which require attention:

The normalization procedure ensures that - if the FIFO is non-empty, there are still elements to be dequeued from the rightmost list. Note that the axiom is specified only for non-normalized FIFOs, which is a matter of convenience for our implementation proofs.

Implementations

In the implementation, we will assume the following invariant: all operations receive normalised FIFOs and return normalised FIFOs.

Axioms are preserved

We proceed to verify that the axioms for $ Dequeue$ are preserved by the implementation.

Conclusion

ADTs offer an interface between object implementation and object behaviour. The FIFO example illustrates the power of ADTs: