我是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]
任何人都可以帮忙解释一下吗?
答案 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 = 3
和x = 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