Haskell 不能';不匹配预期的类型'Int';使用实际类型[Int]
我正在编写一个程序,将列表中的数字相加:Haskell 不能';不匹配预期的类型'Int';使用实际类型[Int],haskell,Haskell,我正在编写一个程序,将列表中的数字相加: [2,3,4,5] = 14 我编译时出错,我不知道程序想要什么: getLimit :: [Int] -> Int getLimit [] = 0 getLimit [x] = sum [x] getLimit [y:yz] = y + getLimit yz 错误是: 提前感谢您的帮助。如评论中所述,您需要在代码中更改以下几项: [y:yz]表示由于方括号而产生的列表列表。您需要用括号替换它,使其看起来像so-(y:yz)那样的head:
[2,3,4,5] = 14
我编译时出错,我不知道程序想要什么:
getLimit :: [Int] -> Int
getLimit [] = 0
getLimit [x] = sum [x]
getLimit [y:yz] = y + getLimit yz
错误是:
提前感谢您的帮助。如评论中所述,您需要在代码中更改以下几项:
[y:yz]
表示由于方括号而产生的列表列表。您需要用括号替换它,使其看起来像so-(y:yz)
那样的head:tail
模式getLimit[]=0
,因此可以消除对单个元素列表的测试,并使用相同的表达式直接转到对所有非空列表的测试foldr
,因为这会使代码更短,并且具有相同的功能。您可以这样重写它:
getLimit :: [Int] -> Int
getLimit = foldr (\x acc -> x + acc) 0
至于为什么我建议使用
foldr
而不是说foldl'
,这是一个很好的解释。不,Haskell比Java更容易学。它没有NullPointerException
s
因此,让我们比较一下Haskell和Java中的getLimit
函数
哈斯克尔
getLimit::[Int]->Int
getLimit[]=0
getLimit(x:xs)=x+getlimitxs
实现getLimit
的问题在于行getLimit[y:yz]=y+getLimit yz
:
y:yz
的类型为[Int]
。因此[y:yz]
的类型是[[Int]]
,这是错误的(y:yz)
getLimit[x]=sum[x]
是不必要的public int-getLimit(int-xs[]){
int length=xs.length;
如果(长度==0)返回0;
否则返回xs[0]+getLimit(Arrays.copyOfRange(xs,1,length));
}
当然,在Java中,您更愿意将用于
循环,而不是递归(在我看来,递归更糟糕,因为循环没有类型,因此编译器无法检查类型)
相比之下,您可以在Haskell中创建循环构造,以进行类型检查。例如,foldl
功能定义为:
foldl::(b->a->b)->b->[a]->b
foldl u a[]=a
foldl f a(x:xs)=foldl f(f a x)xs
这相当于以下JavaScript代码(对不起,我不知道如何在Java中使用泛型):
函数foldl(f,a,xs){
for(变量i=0,l=xs.length;i用例
结论
Haskell比Java好得多。Haskell最好的特性之一是泛型。例如,我们可以使getLimit
成为一个通用函数,它适用于所有类型的数字(不仅仅是Int
s):
getLimit::Num a=>[a]->a
getLimit[]=0
getLimit(x:xs)=x+getlimitxs
我们唯一更改的是函数的类型签名。其他一切都没变。试着用Java做同样的事情。y:yz是一个列表。所以[y:yz]是一个列表列表。getLimit接受整数列表,而不是整数列表([[Int]])。此外,我认为应该消除[x]情况。如果允许使用sum
,那么为什么不直接生成getLimit=sum
的简单答案呢?从GHC编译器中得到的许多错误,稍后运行程序并到达代码行时,也会从JVM中得到。这些错误是你的朋友。Haskell编译器确实很挑剔,而且往往抱怨很多。虽然有更多的编译时错误可能会让人恼火,但作为回报,运行时错误会更少。Haskell程序员实际上喜欢被迫证明他们的程序(部分)是正确的,因为他们知道这一努力将在长期内得到回报,特别是在构建大型程序时。