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.
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.
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.
_
in my example with names--_
in a pattern just means that you don't care about the value at that position. –
Momently !!
, because it's partial, and it's even worse to suggest using a list for accessing an item by index. Vector's !?
on the other hand is fine. –
Sverdlovsk You might like to use the selection functions from the tuple package.
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.
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
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"]
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 !
© 2022 - 2024 — McMap. All rights reserved.