jason
jason

Reputation: 7164

How to get nth element from a 10-tuple in Haskell?

I have to get nth element in a Haskell tuple. And the tuples are like this : (3,5,"String1","String2","String3","String4","String5","String6","String7","String8","String9","String10"). Can you give me an idea so that I can solve this problem? Thanks.

Upvotes: 34

Views: 72034

Answers (7)

Salim Tabellout
Salim Tabellout

Reputation: 1

say for example you have 4 directions, West East North and South, and you want to extract the value of each of those ( let's suppose that the tuple has the direction in this order W E N S)

Coord::Int ->Int ->Int ->Int ->(Int,Int,Int,Int)
Coord a b c d = (a,b,c,d)

myCoord = Coord 0 10 0 5

if you try and extract the values like this

let (W,E,N,S)= myCoord

your compiler will scream at you, to counter that, you'll have to have getters for each of your values ( Yes individually)

getW (W,_,_,_) = W
getE (_,E,_,_) = E
getN (_,_,N,_) = N
getS (_,_,_,S) = S

and there you go !

Upvotes: 0

Marcello
Marcello

Reputation: 71

I think you better use a record type, like:

data MyRec = MyRec {myrecfoo::Double, myrecbar::String, myrecbaz::String}

and then use the record accessors:

baz = myrecbaz rec

But if you want/need to stick with tuples and have less than 20 fields you can use Control.Lens.Tuple

Upvotes: 1

Zoey Hewll
Zoey Hewll

Reputation: 5385

If you only need to do this once per tuple, and you need all the elements at once, you can simply use

let (x, y, s1, s2, s3, s4, s5, s6, s7, s8) = someTuple
in ...

and use the values directly.

Upvotes: 6

Alex
Alex

Reputation: 480

I have seen your question when i was searching a solution for the same problem. I have read the "!!" operator is a bad solution. I have thought a solution:

For example, if you have three elements for each tuple in your list you can do this:

nTuple :: [(a, a, a)] -> Integer -> Integer -> [a]
nTuple list group position = [ fst x | x <- (concat [ fst x | x <- (zip [(zip[t1, t2, t3][0..]) | (t1, t2, t3) <- list ] [0..]) , snd(x) == group ]) , snd(x) == position]

Now, some test cases:

*Main> nTuple [("l","m","n"),("o","p","q"),("r","s","t")] 2 1
["s"]

*Main> nTuple [("l","m","n"),("o","p","q"),("r","s","t")] 0 2
["n"]

*Main> nTuple [("l","m","n"),("o","p","q"),("r","s","t")] 100 2
[]

*Main> nTuple [("l","m","n"),("o","p","q"),("r","s","t")] 2 100
[]

Explication step by step of the above function:

1.Split elements and put an index:

[ zip[t1,t2,t3][0..] | (t1,t2,t3) <- [("l","m","n"),("o","p","q"),("r","s","t")]]

result: [[("l",0),("m",1),("n",2)],[("o",0),("p",1),("q",2)],[("r",0),("s",1),("t",2)]]

2.For each list put an index. Now we have groups and positions within each group.

zip [[("l",0),("m",1),("n",2)],[("o",0),("p",1),("q",2)],[("r",0),("s",1),("t",2)]] [0..]

result: [([("l",0),("m",1),("n",2)],0),([("o",0),("p",1),("q",2)],1),([("r",0),("s",1),("t",2)],2)]

3.We can select a group. For example the group number 1 (first group is the 0) with "snd(x)==1"

[ fst x | x <- [([("l",0),("m",1),("n",2)],0),([("o",0),("p",1),("q",2)],1),([("r",0),("s",1),("t",2)],2)] , snd(x) == 1 ]

result: [[("o",0),("p",1),("q",2)]]

4.We have a list of lists. Whe concatenate tuples in a single list of tuples

concat [[("o",0),("p",1),("q",2)]]

result: [("o",0),("p",1),("q",2)]

5.Finally, we get a element by index. In this example we get the 2nd element (first element is the "0" position)

[ fst x | x <- [("o",0),("p",1),("q",2)] , snd(x) == 2]

result ["q"]

Upvotes: 0

Daniel Wagner
Daniel Wagner

Reputation: 152707

You might like to use the selection functions from the tuple package.

Upvotes: 26

DiegoNolan
DiegoNolan

Reputation: 3766

As you may or may not know fst and snd only work for 2-element tuples ie

fst' (a,b) = a

You have to write you own as far as I know

get5th (_,_,_,_,a,_,_,_,_,_) = a

As you can see you may want to define your own type.

Upvotes: 49

Tikhon Jelvis
Tikhon Jelvis

Reputation: 68152

You could do it with pattern matching. Just like you can match against a two- or three-value tuple, you can match against a ten-value tuple.

let (_, _, _, _, _, _, _, _, _, x, _, _) = tuple in x

However, chances are you don't want to do that. If you're trying to get the nth value out of a tuple, you're almost definitely using the wrong type. In Haskell, tuples of different lengths are different types--they're fundamentally incompatible. Just like Int and String are different, (Int, Int) and (Int, Int, Int) are also completely different.

If you want a data type where you can get the nth element, you want a list: something like [String]. With lists, you can use the !! operator for indexing (which starts at 0), so you could just do:

myList !! 9

to get the 10th element.

Given your example, I suspect you want a type like (Int, Int, [String]) rather than a gigantic tuple. This will let you have two numbers and any number of strings; you can get the strings by index using the !! operator as above.

Upvotes: 48

Related Questions