Add a element at the end of list in Haskell

纵然是瞬间 提交于 2019-12-25 05:52:44

问题


i'm a beginner in Haskell and i'm trying to add an element at the end of a list.

I enter a list like [1,2,3,4] and a number 10. I want an output like this [1,2,3,4,10].

My code:

func a [] = a
func a (x:xs) = x : func a (x:xs)

But i'm getting that error:

Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall a. (Num a, Num [a]) => [a]

Can anyone help with a explanation ?


回答1:


You need to understand that what's happening with your definitions of the functions on the left side of the equals sign is "pattern matching".

With the following statement, you're basically saying

func a [] = a
...

I want first to accept an element of any type, i.e. a, as first parameter, and an empty list as the second parameter, i.e. []. If that's the case, you want to return a. The problem is, you want to return a list [a] (you will see later in this answer why).

With the second part of your function definition (this means that the first "pattern" has not matched against your inputs) you're saying: I accept an element of any type, i.e. a, and a non-empty list, i.e. (x:xs). (x:xs) is a way to say: ok, I have a list and x is the first element of that list. The rest of the list I call xs, which could be empty; in that case, your original list would be a list of size one, i.e. just [x].

...
func a (x:xs) = x : func a (x:xs)

What you return if the pattern is matched is

... = x : func a (x:xs)

which means that you're taking the first element of the list passed as the second parameter (i.e. x) and prepending it to the result of func a (x:xs).

Given this description of your problem, here's a possible solution:

func a [] = [a]
func a (x:xs) = x : func a xs

I would like to note two things here. In the first pattern, i.e func a [] = [a], I return a list, i.e. [a]. In the second pattern, I pass xs to func, i.e. func a xs. In both cases I return a list!

Why does this work? Lets have a look at an example. Let's say you call func like func 3 [1, 2]. Then this is what would happen.

Since [1, 2] is not an empty list, you do not match against the first pattern, so let's see the second; yes, we match against the second. Now we have that a = 3, x = 1 (the start of the list) and xs = [2]. So we then have 1 : func 3 [2]. So we recurse! We now have a = 3 (same as before), x = 2 and xs = [] (i.e. an empty list). So we proceed with the function body and we do 2 : func 3 []. Finally, func 3 [] matches against the first pattern, and you return [3]. But to what? Well, to 2 : [3], which returns to what? To 1 : 2 : [3].




回答2:


Compare:

func a (x:xs) = x : func a (x:xs)
        --      ^^^^^^^^^^^^^^^^^  returns a list
func a [] = a
        --  ^  returns a non-list

Hence the type error. You probably want [a] or a : [] instead.

(Further, the recursive call is wrong, since you pass again the whole list x:xs in it. The list should get smaller else you will never reach the base case.)



来源:https://stackoverflow.com/questions/42798257/add-a-element-at-the-end-of-list-in-haskell

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!