Haskell-汇总列表的前n个元素 [英] Haskell - Sum up the first n elements of a list

查看:96
本文介绍了Haskell-汇总列表的前n个元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Haskell的新手.

I´m new to Haskell.

假设我想用自己生成的函数总结列表的前 n 个元素.我不知道如何与Haskell一起执行此操作.我只知道如何总结整个给定列表,例如

Let´s say I want to sum up the first n elements of a list with a generated function on my own. I don´t know how to do this with Haskell. I just know how to sum up a whole given list, e.g.

sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs

例如,为了汇总列表的前 n 个元素

In order to sum up the first n elements of a list, for example

[1..10]中获取前 5 个数字,即 1 + 2 + 3 + 4 + 5 = 15

take the first 5 numbers from [1..10], which is 1+2+3+4+5 = 15

我认为我可以做这样的事情:

I thought I could do something like this:

sumList :: Int -> [Int] -> Int
sumList take [] = 0
sumList take (x:xs) = x + take $ sumList xs

但这不起作用...怎么了?

But it doesn´t work... What´s wrong?

推荐答案

因此,您知道如何对列表中的数字求和,

So you know how to sum up the numbers in a list,

sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs

,并且如果该列表中包含的元素不超过5个,则如果您确实打算在参数列表中添加不超过5个元素,则此函数甚至将返回正确的结果.通过重命名此功能,使我们的期望明确化

and if that list has no more than 5 elements in it, this function will even return the correct result if you indeed intended to sum no more than 5 elements in an argument list. Let's make our expectations explicit by renaming this function,

sumUpToFiveElements :: [Int] -> Int
sumUpToFiveElements [] = 0
sumUpToFiveElements (x:xs) = x + sumUpToFiveElements xs

对于超过五个的列表,它不会返回正确的结果,但是至少名称正确.

it won't return the correct result for lists longer than five, but at least the name is right.

我们可以解决这个问题吗?我们最多可以数5吗?我们还能像往前一样在输入列表中前进时最多计数5个吗?

Can we fix that? Can we count up to 5? Can we count up to 5 while also advancing along the input list as we do?

sumUpToFiveElements :: Int -> [Int] -> Int
sumUpToFiveElements counter [] = 0
sumUpToFiveElements counter (x:xs) = x + sumUpToFiveElements (counter + 1) xs

这当然不是正确的.我们现在进行计数,但是由于某些原因,我们忽略了计数器.如果我们希望不超过5个元素,那么对计数器做出反应的正确时间是什么时候?让我们尝试counter == 5:

This still isn't right of course. We do now count, but for some reason we ignore the counter. What is the right time to react to the counter, if we want no more than 5 elements? Let's try counter == 5:

sumUpToFiveElements :: Int -> [Int] -> Int
sumUpToFiveElements 5       [] = 0
sumUpToFiveElements counter [] = 0
sumUpToFiveElements counter (x:xs) = x + sumUpToFiveElements (counter + 1) xs

但是为什么我们要求列表达到5时也要为空?我们不要这样做:

But why do we demand the list to also be empty when 5 is reached? Let's not do that:

sumUpToFiveElements :: Int -> [Int] -> Int
sumUpToFiveElements 5       _  = 0        -- the wildcard `_` matches *anything*
sumUpToFiveElements counter [] = 0
sumUpToFiveElements counter (x:xs) = x + sumUpToFiveElements (counter + 1) xs

成功!现在,当达到5时,我们停止计数!此外,我们也停止求和!!

Success! We now stop counting when 5 is reached! More, we also stop the summation!!

等等,counter的初始值是多少?我们没有指定它,因此函数用户(即我们自己)很容易犯错并使用不正确的初始值.顺便说一句, 正确的初始值是什么?

Wait, but what was the initial value of counter? We didn't specify it, so it's easy for a user of our function (that would be ourselves) to err and use an incorrect initial value. And by the way, what is the correct initial value?

好的,让我们这样做:

sumUpToFiveElements :: [Int] -> Int
sumUpToFiveElements xs = go 1 xs     -- is 1 the correct value here?
  where
    go counter  _ | counter == 5 = 0  
    go counter [] = 0
    go counter (x:xs) = x + go (counter + 1) xs

现在,我们没有那种无关紧要的参数,它使我们的定义变得如此脆弱,因此容易出现用户错误.

Now we don't have that extraneous argument that made our definition so brittle, so prone to a user error.

现在是重点:

通用化! (通过将一个示例值替换为符号值;将5更改为n).

Generalize! (by replacing an example value with a symbolic one; changing 5 to n).

sumUpToNElements :: Int -> [Int] -> Int
sumUpToNElements n xs = .......
   ........

完成.

另一个建议:在学习Haskell的初期,不要使用$.使用 explicit 括号.

One more word of advice: don't use $ while at the very beginning of your learning Haskell. Use explicit parens.

sumList take (x:xs) = x + take $ sumList xs 

解析为

sumList take (x:xs) = (x + take) (sumList xs)

这将两个不相关的数字加在一起,然后将结果用作要以(sumList xs)作为参数调用的函数(换句话说,这是一个错误).

This adds together two unrelated numbers, and then uses the result as a function to be called with (sumList xs) as an argument (in other words it's an error).

如果您使用显式括号,则可能不会这样写.

You probably wouldn't write it that way if you were using explicit parens.

这篇关于Haskell-汇总列表的前n个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆