Haskell,即使没有指定我的类型,也会出现以下错误:cannot';t匹配类型'a';使用`[a]'`a';是受约束的刚性类型变量

Haskell,即使没有指定我的类型,也会出现以下错误:cannot';t匹配类型'a';使用`[a]'`a';是受约束的刚性类型变量,haskell,types,compiler-errors,Haskell,Types,Compiler Errors,所以我意识到这可能是一个重复的问题,因为在堆栈溢出上报告了许多错误,但没有一个解决方案适用于我的问题 所以我有以下功能: elementAt' :: Integral b => [a] -> b -> a elementAt' [x:_] 1 = x elementAt' [x:xs] y = elementAt' xs yminus1 where yminus1 = y - 1 如果你想知道这是问题3。函数的目标是将列表和索引作为输入,并返回该索引处的值(从1开始)

所以我意识到这可能是一个重复的问题,因为在堆栈溢出上报告了许多错误,但没有一个解决方案适用于我的问题

所以我有以下功能:

elementAt' :: Integral b => [a] -> b -> a
elementAt' [x:_] 1 = x
elementAt' [x:xs] y = elementAt' xs yminus1
    where yminus1 = y - 1
如果你想知道这是问题3。函数的目标是将列表和索引作为输入,并返回该索引处的值(从1开始)。我不想找到问题的解决方案,如果我想,我可以看看提供的解决方案。但我犯了个错误,我不明白。我使用的是eclipseFP,haskell的eclipse插件,它在函数的“[x:\”和“[x:xs]”部分下面加了下划线,错误如下:

Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for elementAt' :: Integral b => [a] -> b -> a
在我看过的所有讨论这个错误的线程中,当有人试图给期望某种类型的东西提供错误的输出时,问题通常会发生。例如,将某物的长度(Int类型)返回为“Num a”变量类型

但在我的例子中,我甚至没有为变量a提供类型。它应该可以是任何东西,对吗?那我为什么会犯这个错误呢?如果我明白为什么会出错,我可以纠正它,但我就是不明白

有人能给我解释一下为什么我会收到这个错误吗

非常感谢你的帮助,谢谢。 -阿萨夫


编辑:到目前为止提供的每个答案都是正确的,谢谢大家提供的有用信息。我将选择我认为最清楚的一个(但我必须等待5分钟才能完成)。

使用括号,而不是括号:
(x:xs)


在没有类型声明的情况下输入定义将显示推断出的类型是
Integral b=>[[a]]->b->a
。没错,您当前的模式与列表列表匹配

像这样的图案

f [pat] = ...
匹配其唯一元素匹配的单件列表。您希望使用
cons
a.k.a.
(:)
而不是要求特定长度,然后需要括号而不是括号:

elementAt' (x:xs) n = ...

错误基本上是这样的:“将
a
(第一个参数的元素)视为一个列表。”

如果要将列表与头和尾匹配,应该使用

elementAt' (x:_) 1 = x
所以,最后

elementAt' :: Integral b => [a] -> b -> a
elementAt' (x:_) 1 = x
elementAt' (x:xs) y = elementAt' xs yminus1
    where yminus1 = y - 1

这是你需要的吗

但在我的例子中,我甚至没有为变量a提供类型。它应该可以是任何东西,对吗

它必须能够是任何东西。根据您的类型签名,函数的用户必须能够使用
a
作为
Int
调用函数,
a
作为
[Char]
调用函数,或者使用“a”作为用户想要调用的任何函数


但是,错误消息告诉您,您定义了函数,因此只能使用
a
作为某个内容的列表来调用它。也就是说,您定义了它,所以第一个参数必须是列表的列表-它不能是其他任何内容的列表。这与您的类型签名相矛盾。

+1用于解释问题的原因,而不仅仅是消除错误。虽然您了解解决方案,但询问者可能没有——您没有解决
问题,请有人向我解释为什么我会收到此错误?
@delnan在上面给出了解释。一般来说,我会尝试给出更详细的答案。为什么不直接写
elementAt'[x:xs]y=elementAt'xs(y-1)
@Vixen这和我写的有什么不同。。。除了包含变量声明之外?显然,无论哪种情况,编译器最终都会做完全相同的事情(如果我错了,请纠正我)。是的,这是一样的,我只是觉得将某个东西声明为yminus1看起来很奇怪,因为y-1在我看来更容易读取,看起来更漂亮
elementAt' :: Integral b => [a] -> b -> a
elementAt' (x:_) 1 = x
elementAt' (x:xs) y = elementAt' xs yminus1
    where yminus1 = y - 1
λ> elementAt' [1,2,3] 2
2