在Haskell的列表末尾添加一个元素

时间:2017-03-14 23:12:37

标签: haskell

我是Haskell的初学者,我正在尝试在列表的末尾添加一个元素。

我输入一个像[1,2,3,4]和数字10这样的列表。我想要一个这样的输出[1,2,3,4,10]。

我的代码:

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

但是我收到了这个错误:

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]

任何人都可以帮忙解释一下吗?

3 个答案:

答案 0 :(得分:1)

比较

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

因此类型错误。您可能需要[a]a : []

(此外,递归调用是错误的,因为你再次传递了整个列表x:xs。列表应该变小,否则你永远不会达到基本情况。)

答案 1 :(得分:1)

您需要了解等号左侧的函数定义所发生的事情是"模式匹配"。

通过以下声明,您基本上是在说

func a [] = a
...

我希望首先接受任何类型的元素,即a作为第一个参数,并将空列表作为第二个参数,即[]。如果是这种情况,您想要返回a。问题是,你想要返回一个列表[a](你会在后面的答案中看到原因)。

使用函数定义的第二部分(这意味着第一个"模式"未与输入匹配)你会说:我接受任何类型的元素,即{{ 1}}和非空列表,即a(x:xs)是一种说法:好的,我有一个列表,(x:xs)是该列表的第一个元素。列表的其余部分我称之为x,可能是空的;在这种情况下,您的原始列表将是一个大小为1的列表,即仅xs

[x]

如果模式匹配,则返回的是

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

表示您将作为第二个参数传递的列表的第一个元素(即... = x : func a (x:xs) )并将其前置于x的结果。

鉴于您对问题的描述,这里有一个可能的解决方案:

func a (x:xs)

我想在这里注意两件事。在第一种模式中,即func a [] = [a] func a (x:xs) = x : func a xs ,我返回一个列表,即func a [] = [a]。在第二种模式中,我将[a]传递给xs,即func。在这两种情况下,我都会返回一个列表!

为什么这样做?让我们来看一个例子。我们假设你像func a xs一样致电func。然后就会发生这种情况。

由于func 3 [1, 2]不是空列表,因此您与第一个模式不匹配,所以让我们看第二个模式;是的,我们匹配第二个。现在我们有[1, 2]a = 3(列表的开头)和x = 1。那么我们就有了xs = [2]。所以我们递归!我们现在有1 : func 3 [2](与以前相同),a = 3x = 2(即空列表)。所以我们继续使用函数体,然后我们进行xs = []。最后,2 : func 3 []与第一个模式匹配,然后返回func 3 []。但到了什么?好吧,到[3],它会回归什么?致2 : [3]

答案 2 :(得分:1)

简单的非递归方法怎么样:

func num xs = xs ++ [num]

或者如果你坚持递归:

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