Haskell code errors - I dont understand what it is asking for

haskell

Solution

You say that you want a function that returns the first component of the second element of the list. The best way to write this function will be by pattern matching. But first, let's think about its type.

Say you want a list of tuples of `(Int,Char)`. This is written as `[(Int,Char)]`. If you want a list of 2-tuples of arbitrary type, you replace the types `Int` and `Char` with type variables, so you end up with the type `[(a,b)]`.

Your function needs to take something of this type, and return the first component of the second element of the list. All of the first components of the tuples have type `a`, so your return type must be `a` as well. So your function's type signature is

f :: [(a,b)] -> a

Now, how do we write this function? The best way is to use pattern matching. This is a neat way to extract the components of a data structure without having to use accessors (aka getters, if you come from an object-oriented background). Let's say we have a function `g :: [a] -> a` which returns the third component of a list. You could write

g :: [a] -> a
g xs = head (tail (tail xs))

but that looks pretty nasty. Another way is to pattern match. A list with three elements `[x,y,z]` can be constructed by doing `x : y : z : []` where `x`, `y` and `z` are all of type `a` (remember that the operator `:` adds items to the front of a list). So we can write:

g :: [a] -> a
g (x : y : z : []) = z

But there's a problem with this - it only works on lists of length three, because our pattern says "Match a list of three elements with the empty list tacked on the end." Instead, we could use the pattern `x : y : z : rest`, where now `rest` matches the rest of the list:

g :: [a] -> a
g (x : y : z : rest) = z

where our pattern now says "Match a list of three elements followed by anything else at all." In fact, we can make it simpler. We aren't going to use the values `x`, `y` or `rest` so we can replace them with the Haskell pattern `_` (underscore). This matches anything, and makes us promise that we aren't going to use that value:

g :: [a] -> a
g (_ : _ : z : _) = z

How can we use this to solve your problem? Well, if you had a list matching the pattern `(w,x) : (y,z) : rest` you would want to return `y`. So you can write:

f :: [(a,b)] -> a
f ( (w,x) : (y,z) : rest ) = y

which will work fine. However, you don't care about the first pair at all, so you can replace `(w,x)` with `_`. You also don't care about the second element of the second tuple or the rest of the list, so you can replace them with `_` as well, getting:

f :: [(a,b)] -> a
f ( _ : (y,_) : _) = y

Checking it in ghci:

ghci> f [(5,'b'),(1,'c'),(6,'a')]
1

So it behaves as you expected it to.

Problem

First time poster, but this site has helped me alot. I am trying to learn Haskell. This is the question i'm asked to answer. Write a function that takes a list (length >=2) of pairs of length and returns the first component of the second element in the list. So, when provided with [(5,’b’), (1,’c’), (6,’a’)], it will return 1. I have done this myself. ``` listtwo :: [([a],b)] -> [a] listtwo [] = [] listtwo [(a,b)] = fst (head (tail [(a,b)])) ``` I am trying to take a list of lists tuples I believe and return the 1st element from the 2nd item in the list. I know if you take out the [(a,b)]'s and replace the second [(a,b)] with a list like the one in the question it works fine. But when I try to make this function work for ANY list of tuples. I get errors. Error I recieve ``` <interactive>:1:27: No instance for (Num [a0]) arising from the literal `6' Possible fix: add an instance declaration for (Num [a0]) In the expression: 6 In the expression: (6, 'a') In the first argument of `listtwo', namely `[(5, 'b'), (1, 'c'), (6, 'a')]' ``` So i'm asking if anyone can help me deciver the errors and mabye explain what I am doing wrong (don't give me the answer, cant learn that way). Appriciate the help, might have more questions if this gets answered. Thank you very much in advance!

Original source