0

I'm trying to combine 2 lists from input but I am getting an error every time. Here is my code:

myAppend :: [a] -> [a] -> [a]
myAppend a b = zipWith (+) a b

Getting this error: "No instance for (Num a) arising from a use of ‘+’"

I was given this solution but it doesn't really make sense to me

myAppend :: [a] -> [a] -> [a]
myAppend [] xs = xs
myAppend (y:ys) xs = y:(myAppend ys xs)

I don't really understand the second and third line.

Can anyone help?

Thanks

3
  • It depends on what you mean by "combine". Your function adds the lists elements pairwise, the other one concatenates the lists. Commented Nov 9, 2022 at 17:09
  • my bad I meant to concatenate them Commented Nov 9, 2022 at 17:12
  • You claim (in your type signature) that myAppend will work with lists of any type, whether that type supports + or not. But then you try to use + anyway. The correct type for myAppend would be Num a => [a] -> [a] -> [a]. Commented Nov 9, 2022 at 18:40

1 Answer 1

1

Your myAppend does not concatenate two lists, it aims to sum elementwise the two lists, so myAppend [1,4,2,5] [1,3,0,2] will produce [2,7,2,7]. It will require a Num a constraint, since it can only work if the elements of the lists are Numbers:

myAppend :: Num a => [a] -> [a] -> [a]
myAppend a b = zipWith (+) a b

As for the solution here it uses recursion. Lists in Haskell are like linked lists: you have a an empty list ("nil") which is represented by the [] data constructor, and a node ("cons") which is represented with (x:xs) where x points to the first item, and xs points to the list of remaining elements. So [1,4,2,5] is short for (1:(4:(2:(5:[])))).

If we want to append [1,4] and [2,5] we thus want to produce a list (1:(4:(2:(5:[])))) out of (1:(4:[])) and (2:(5:[])). This means we create a linked list with all the elements of the first list, but instead of pointing to the empty list [], we let it point to the second list for the remaining elements. We do this through recursion:

myAppend (y:ys) xs = y : myAppend ys xs

will match if the first list unifies with the (y:ys) pattern. In that case we thus produce a list with y as first element, and the result of myAppend ys xs as as list of remaining elements ("tail"). Eventually we will thus call myAppend ys xs with the empty list [] as first item. In that case, we thus return the second list instead of the empty list, to append the second list to it.

We thus make calls that look like:

   myAppend [1, 4]     [2, 5]
=  myAppend (1:(4:[])) (2:(5:[]))
-> 1 : (myAppend (4:[]) (2:(5:[])))
-> 1 : (4 : (myAppend [] (2:(5:[]))))
-> 1 : (4 : (2:(5:[]))
=  [1, 4, 2, 5]
Sign up to request clarification or add additional context in comments.

2 Comments

Where you wrote "(1:(4:[])) and (2:5:[])" is that correct or should it be (1:(4:[])) and (2:(5:[]))? Thanks
@user20338595 : associatse to the right, so foo:bar:baz and foo:(bar:baz) are the same thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.