Accessing a Specific Element in a Tuple

74,803

Solution 1

What prevents the language from having the special construct you want is its design. The designers just didn't put this in, because it would complicate the language definition, which is quite minimalistic. fst and snd are library functions for the common case of pairs; you can define all the others yourself, or better, define record types for your data so that your data members have appropriate names.

(It may be that GHC has an extension to do this, but I haven't encountered one; check the docs or ask on the mailing list to be sure.)

Solution 2

Check out the tuple library on hackage. It has overloaded functions for various operations on tuples (up to a predefined size).

Solution 3

N-tuples are not a data structure for indexing via an Int key, instead, you should look at one indexed-biased data structures, such as arrays or finger-trees.

Now, one could imagine writing a typeclass for a family of tuple types providing an index operation, however, we already have arrays for that, and there's a lot of boilerplate necessary to make tuples of any type seamlessly provide this operation. The power gained isn't worth the effort.

Solution 4

Why can't this be done easier? Or maybe there is some easy way?

It can be easier using a recent alternative the lens package. The Tuple module has selectors for up to 9 element tuples and it is straight forward to define more if needed.

> import Control.Lens
> data A = A deriving (Show)
> (1, '2', "3", A) ^. _1
1
> (1, '2', "3", A) ^. _2
'2'
> (1, '2', "3", A) ^. _3
"3"
> (1, '2', "3", A) ^. _4
A

You can also use the lens package to update elements polymorphically, change type on update.

With and without infix operators:

> (1, '2', "3", A) & _1 .~ "wow"
("wow",'2',"3",A)
 > set _1 "wow" (1, '2', "3", A)
("wow",'2',"3",A)

The github readme is a good place to start to find out more about the underlying theory as well as numerous examples.


Not just tuples

Similar syntax works for Traverables and Foldables, so Trees, Maps, Vectors, etc. For example if I had a list of tuples I can access the third tuple element at the 1 index by composing the element 1 to access the first index element with _3 to access the third tuple element.

[(1,2,3),(4,5,6),(7,8,9)] ^? element 1 . _3
Just 6

Solution 5

The question of an approach to doing this using template haskell was previously addressed here.

An example of its usage:

> $(sel 2 3) ('a','b','c')
'b'
> $(sel 3 4) ('a','b','c','d')
'c'

From here.

Share:
74,803

Related videos on Youtube

Micha Wiedenmann
Author by

Micha Wiedenmann

Updated on January 25, 2020

Comments

  • Micha Wiedenmann
    Micha Wiedenmann over 4 years

    Haskell-newbie reporting in. Question is as follows: In Haskell, we have fst and snd that return the first and the second elements of a 2-tuple. Why don't we have an easy way of accessing the i-th element from any tuple? Right now I have a 3-tuple, I want to read the 1st element and the only way of accomplishing this task is doing pattern-matching trickery. Why can't this be done easier? Or maybe there is some easy way?

    • Admin
      Admin about 13 years
      Anything wrong with third (_, _, x) = x?
    • Admin
      Admin about 13 years
      That's exactly what I'm talking about. What prevents the language from having a special construct that would spare us the trouble of writing functions like the one you jsut mentioned?
    • Admin
      Admin about 13 years
      What would such a construct look like? It can't be a function, not with the current type system, and introducing a new language-level construct isn't worth it by any standards, especially considering that larger tuples are rare and rarely a good idea (Have you heard the expression "every new features starts out with -100 points"?).
    • Admin
      Admin about 6 years
      Possible duplicate of N-Ary Versions of Tuple Functions
  • John L
    John L about 13 years
    ghc does not have an extension for this, but there are libraries which provide it (see augustss's answer).
  • BMeph
    BMeph about 13 years
    My impulse ewould be to say "-1 for forcing the user to include the tuple size to 'sel', especially since it always immediately precedes the tuple it selects from," but of course, the -1 is on the TH writer, not the user.
  • wires
    wires over 12 years
    while this answer is not incorrect, it is besides the point; See Don Steward's answer below