Using the lists I can get the element of the index X
using the operator !!
.
For example:
Prelude> let lista = [2,4..20]
Prelude> lista
[2,4,6,8,10,12,14,16,18,20]
Prelude> lista !! 0
2
Prelude> lista !! 5
12
Now that I am learning about tuples in Haskell, if I try to access an element by its index in the same way, I get an error:
Prelude> let tupla = (1, "Hola", 'Z')
Prelude> tupla
(1,"Hola",'Z')
Prelude> tupla !! 1
<interactive>:9:1:
Couldn't match expected type `[a0]'
with actual type `(Integer, [Char], Char)'
In the first argument of `(!!)', namely `tupla'
In the expression: tupla !! 1
In an equation for `it': it = tupla !! 1
What is the correct way to access elements of tuples by their index?
Tuples are not data structures that are indexed by an integer.
To access the elements of a pair, you can make use of the
fst
and functionssnd
. If you want to access, for example, the third element of the tuple you can use pattern matching:Or you can also use the one
select
from the tuple package .However, the use of very large tuples is not recommended. Very large tuples generally indicate that another type should be used.
To add to Nicolocodev's answer, something to note is the following important difference between lists and tuples in Haskell (and in statically typed languages, generally):
This has important consequences for your question. Let's look at the type of the function that extracts an element from a list:
We can see that the type variable
a
appears twice in the function type:[a]
;But now let's try to imagine: what would be the type of the function that obtains the element of a tuple by its index? We can start by outlining the type, using
_tupla
and_elemento
as blanks for the types we'll try to fill:The first problem we face is that there is no type in basic Haskell that includes tuples of all sizes in its values. That is, the tuples of two, three, four or etc. elements are different types, so we can't write a function that accepts tuples of any size as an argument. For tuples of each size we need a separate function:
And now the second problem: with what type do we fill the blanks that I marked with
_elemento
? The difficulty is that depending on the index that we are given as an argument, the type of the value in that element of the tuple is different. So again, we can't write such a function literally; we need to make some change to the problem. We could, for example, do the following, introducing sum types ("sum types") that are responsible for representing the fact that the result is a sum of cases with heterogeneous types:Or we could require that all the elements of the tuples be of the same type:
Now our functions don't work on all tuples—only those whose elements are of homogeneous type. But by doing this we have eliminated half the difference between tuples and lists—the only difference that remains is that lists of different lengths are nonetheless values of the same type. Remember that this was the reason why we introduced
elementoDeTupla2
,elementoDeTupla3
andelementoDeTupla4
as separate functions; so now, to eliminate duplication, we end where we started, using lists:And this brings us to the answer to your question: if you need to get elements by index, this indicates that you need to use lists, not tuples. (Though in reality it would usually be better in that case to use
Vector
, which allows access by index in constant time.)