Home > Enterprise >  Find the nth element in a tuple using the function below
Find the nth element in a tuple using the function below

Time:10-09

"Use the below function with two parameters:

nth :: (a,a,a,a,a) -> Int -> a

where the Int value should return the Int-th value of the five-element tuple." I tried:

nth (a,b,c,d,e) x = (a,b,c,d,e) !! x

But GHC gave me an error message:

file.hs:11:21: error:
* Couldn't match expected type `[a1]'
              with actual type `(a, b, c, d, e)'
* In the first argument of `(!!)', namely `(a, b, c, d, e)'
  In the expression: (a, b, c, d, e) !! x
  In an equation for `nth':
      nth (a, b, c, d, e) x = (a, b, c, d, e) !! x
* Relevant bindings include
    e :: e (bound at file.hs:11:14)
    d :: d (bound at file.hs:11:12)
    c :: c (bound at file.hs:11:10)
    b :: b (bound at file.hs:11:8)
    a :: a (bound at file.hs:11:6)
    nth :: (a, b, c, d, e) -> Int -> a1
      (bound at file.hs:11:1)

What should I do? How should I write the tuple part of this equation? Thanks for your answers in advance!

CodePudding user response:

You can not use (!!) :: [a] -> Int -> a since, as the signature says, it works on lists, not tuples. You can work with pattern matching and implement this as:

nth :: (a, a, a, a, a) -> Int -> a
nth (a, _, _, _, _) 0 = a
nth (_, b, _, _, _) 1 = b
nth (_, _, c, _, _) 2 = c
nth (_, _, _, d, _) 3 = d
nth (_, _, _, _, e) 4 = e

There have been proposals where a 3-tuple is defined as (a, (b, c)) such that it is thus a recursive structure where an n-tuple is defined as a 2-tuple with an n-1-tuple as second item. But this is not the case (at the moment).

CodePudding user response:

You can avoid some of the repetition from the existing pattern-matching solutions by separating the pattern match for the tuple from the match on n:

nth :: (a, a, a, a, a) -> Int -> a
nth (a, b, c, d, e) n = case n of
  0 -> a
  1 -> b
  2 -> c
  3 -> d
  4 -> e

You should also consider what you want to happen when n is not in the range [0, 4]. As written, you will get a non-exhaustive pattern error at runtime. It would be more honest to either return a Maybe a or take a more constrained type as input, like

data QuintupleIndex = Zero | One | Two | Three | Four

CodePudding user response:

The (!!) function only works on lists.

For tuples, at least those of more than 2 elements, the only way to access the elements is by direct pattern matching:

nth :: (a,a,a,a,a) -> Int -> a
nth (a, _, _, _, _) 0 = a
nth (_, a, _, _, _) 1 = a
nth (_, _, a, _, _) 2 = a
nth (_, _, _, a, _) 3 = a
nth (_, _, _, _, a) 4 = a

(note the _s, which mean "I don't care what this value" is. You could give them a name instead - eg match on (a, b, c, d, e) on each line and have the returned value being a on the first line, b on the second and so on. But it's less visual "noise" to only name the values you care about.)

Also note that this function will crash with a "non-exhaustive patterns" error if the integer argument is anything outside 0-4. But using (!!) on a list of 5 elements has a similar flaw. You can easily add a default case to the end, although that's not easy when working with a completely generic type a because there is no value that will work as a return value of any type the function might be called with!

CodePudding user response:

a simple solution using guards is as follows:

nth :: (a,a,a,a,a) -> Int -> a
nth (a, b, c, d, e) i
  | i == 0    = a
  | i == 1    = b
  | i == 2    = c
  | i == 3    = d
  | otherwise = e
  • Related