Question

I'm new to Haskell (and functional programming in general) and was wondering how I can access a new element that I've added to a list using the cons (:) operator?

For example, using WinGHCi I create a new list and access the first element:

ghci> let a = [1,2,3]
ghci> a!!0
1

The prompt returns 1, the value of the first element, cool. Now I append a new value to the front of the list and try to access it:

ghci> 5:a
[5,1,2,3]
ghci> a!!0
1

It looks like the list items don't get re-indexed. I tried getting a negative index to work and other such things but the compiler didn't seem to approve. The tutorials I'm reading just skip over it and I couldn't find anything of use online. How do I get the value "5" from the list?

Thanks for the help and sorry if this is a very basic question.

Was it helpful?

Solution

This idea lies at the core of functional programming: you are (usually) not modifying data in place. So you don't add an item to a list: you create a new list without modifying the old one.

This allows for many nice things, sharing for instance, because you are never changing the old data and so you can keep referring to it. But it also imposes a burden if you are accustomed to other programming paradigms: you have to change your way to approach things (and often you have to change your data structures/algorithms because they were relying on in-place modification of a data structure).

In your example, just give a new name to the cons'ed list:

let a = [1, 2, 3]
let b = 5:a

OTHER TIPS

Your misunderstanding is fundamental: cons does not destructively modify anything.

5:a (where a = [1,2,3]) evaluates to [5,1,2,3], and that is what the interpreter is showing you.

Let me illustrate with (+) as well as (:)

Prelude> 4+5
9
Prelude> let z = 5
Prelude> z
5
Prelude> 4+z
9
Prelude> z
5
Prelude> let y = 4+z
Prelude> y
9
Prelude> z
5

versus

Prelude> let a = [1,2,3]
Prelude> a
[1,2,3]
Prelude> 5:a
[5,1,2,3]
Prelude> a
[1,2,3]
Prelude> let b = 5:a
Prelude> b
[5,1,2,3]
Prelude> a
[1,2,3]

Bindings made with 'let' never change, but new ones can be made. If a new binding has the same name as an old binding then the old binding is "shadowed" not mutated.

Lists are immutable:

Prelude> let xs = [1,2,3]
Prelude> 4:xs
[4,1,2,3]
Prelude> xs
[1,2,3]
Prelude> let ys = 4:xs
Prelude> ys
[4,1,2,3]

If you wanna change the elements of the data structure use Arrays.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top