Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lists in Haskell : data type or abstract data type?

From what I understand, the list type in Haskell is implemented internally using a linked list. However, the user of the language does not get to see the details of the implementation, nor does he have the ability to modify the "links" that make up the linked list to allow it to point to a different memory address. This, I suppose, is done internally.

How then, can the list type be qualified as in Haskell ? Is it a "data type" or an "abstract data type"? And what of the linked list type of the implementation ?

Additionally, since the list type provided by the Prelude is not a linked list type, how can the basic linked list functions be implemented ?

Take, for example, this piece of code designed to add an element a at the index n of a list :

add [] acc _ _ = reverse acc
add (x:xs) acc 0 a = add xs (x:a:acc) (-1) a 
add (x:xs) acc n a = add xs (x:acc) (n-1) a

Using a "real" linked list, adding an element would just consist of modifying a pointer to a memory address. This is not possible in Haskell (or is it ?), thus the question : is my implementation of adding an element to a list the best possible one, or am I missing something (the use of the reverse function is, I think, particularly ugly, but is it possible to do without ?)

Please, do not hesitate to correct me if anything I have said is wrong, and thank you for your time.

like image 309
CharlieP Avatar asked Dec 21 '09 19:12

CharlieP


People also ask

Is a list An abstract data type?

In computer science, a list or sequence is an abstract data type that represents a finite number of ordered values, where the same value may occur more than once.

What type is a list in Haskell?

In Haskell, lists are a homogenous data structure. It stores several elements of the same type. That means that we can have a list of integers or a list of characters but we can't have a list that has a few integers and then a few characters.

What is an abstract data type in Haskell?

Definition. An abstract data type is a type with associated operations, but whose representation is hidden. Common examples of abstract data types are the built-in primitive types in Haskell, Integer and Float. Haskell supports the definition of abstract data types via the module system.

What is data type in Haskell?

In Haskell, you can have many constructors for your data type, separated by a vertical bar | . Each of your constructors then has its own list of data types! So different constructors of the same type can have different underlying data! We refer to a type with multiple constructors as a “sum” type.


2 Answers

You're confusing mutability with data structure. It is a proper list — just not one you're allowed to modify. Haskell is purely functional, meaning values are constant — you can't change an item in a list any more than you could turn the number 2 into 3. Instead, you perform calculations to create new values with the changes you desire.

You could define that function most simply this way:

add ls idx el = take idx ls ++ el : drop idx ls

The list el : drop idx ls reuses the tail of the original list, so you only have to generate a new list up to idx (which is what the take function does). If you want to do it using explicit recursion, you could define it like so:

add ls 0 el   = el : ls
add (x:xs) idx el
  | idx < 0   = error "Negative index for add"
  | otherwise = x : add xs (idx - 1) el
add [] _ el   = [el]

This reuses the tail of the list in the same way (that's the el : ls in the first case).

Since you seem to be having trouble seeing how this is a linked list, let's be clear about what a linked list is: It's a data structure consisting of cells, where each cell has a value and a reference to the next item. In C, it might be defined as:

struct ListCell {
void *value; /* This is the head */
struct ListCell *next; /* This is the tail */
}

In Lisp, it's defined as (head . tail), where head is the value and tail is the reference to the next item.

In Haskell, it's defined as data [] a = [] | a : [a], where a is the value and [a] is the reference to the next item.

As you can see, these data structures are all equivalent. The only difference is that in C and Lisp, which are not purely functional, the head and tail values are things you can change. In Haskell, you can't change them.

like image 137
Chuck Avatar answered Sep 21 '22 05:09

Chuck


Haskell is a purely functional programming language. This means no change can be done at all.

The lists are non-abstract types, it's just a linked list.

You can think of them defined in this way:

data [a] = a : [a] | []

which is exactly the way a linked list is defined - A head element and (a pointer to) the rest.

Note that this is not different internally - If you want to have more efficient types, use Sequence or Array. (But since no change is allowed, you don't need to actually copy lists in order to distinguish between copies so, which might be a performance gain as opposed to imperative languages)

like image 27
Dario Avatar answered Sep 21 '22 05:09

Dario