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]
    是不必要的
  • JAVA
    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 简言之,我们为循环a类型给出了一个特定的
    用例

    结论 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程序员实际上喜欢被迫证明他们的程序(部分)是正确的,因为他们知道这一努力将在长期内得到回报,特别是在构建大型程序时。