1

我正在尝试迭代一个列表并将所有数字平方并将它们加在一起

sumsq  (x:xs) = 
let total = 0
loop length(x:xs) (x:xs) total


loop 0 (x:xs) = return ()
loop n (x:xs)  total = 
do
    let 
        sq = ((x:xs)!!n)^2
        total = total + sq
    loop ((n-1) (x:xs) total)

但我得到了parse error in loop。我哪里错了?

还有更好的方法吗?

4

4 回答 4

3

首先 - 你错过了空间!这很重要。

其次,你忘记了inlet ... in. 我们不能使用inin do-notation:

sumsq  (x:xs) = 
   let total = 0 in
   loop length(x:xs) (x:xs) total

第三,您不要使用xandxs形式(x:xs)

sumsq  xs = 
    let total = 0 in
    loop (length xs) xs total

我们团结length xs在一个街区。它是第四个。

第五,我们有 3 个,而不是 2 个循环参数:

loop 0 xs total  = return total

第六,(!!)从 0 开始工作,但你从 1 开始使用它,所以(xs !! (n -1))是对的

第七,你不需要使用 monad,只需要递归。所以,摆脱returndo

第八。你有无限递归total = total + smth

第九,我们不能使用参数作为元组,所以,你最终的工作结果是:

sumsq  xs = 
    let total = 0 in
    loop (length xs) xs total


loop 0 xs total = total
loop n xs total = loop (n-1) xs total1
    where 
        sq = (xs !! (n -1)) ^2
        total1 = total + sq

更新

如果我们谈论的是复杂性,那就不好了——O(n^2)正如评论中提到的那样:对于每个元素,我们都在寻找这个元素。我们可以简化循环函数并去掉n参数:

loop []     total = total
loop (x:xs) total = loop xs total1
    where 
        sq = x ^ 2
        total1 = total + sq

以及sumsq我们编写的函数:

sumsq  xs = loop xs 0

PS这是一个更容易实现的功能sumsq = sum. map (^ 2)

于 2013-10-07T15:56:06.580 回答
3

如果我对您的理解正确,您可以简单地使用mapand来执行此操作sum

Prelude> let myFun = sum . map (^2)
Prelude> myFun [1, 2, 3]
14

或使用foldl1和 lambda:

Prelude> let myFun' = foldl1 (\s x -> s + x^2)
Prelude> myFun' [1, 2, 3, 4]
30
于 2013-10-07T15:58:48.837 回答
3

当然,这样的事情会是通常的方法吗?

sumSquared :: [Integer] -> Integer
sumSquared [] = 0
sumSquared (x:xs) = (x * x) + sumSquared xs

foldr或者你可以用, 或sumand更简洁地做到这一点map(就像@soon's answer)

于 2013-10-07T15:59:52.707 回答
1

thedo必须比 word 缩进更多loop

除此之外,你根本不需要do(或return),除非你能回答这个问题是为了哪个 monad?

您的代码存在更多问题。最严重的情况之一是:

您似乎不知道“模式匹配”是什么,也不知道它有什么用处。你真的很想了解它,否则你写不出任何好的程序。

于 2013-10-07T16:00:32.437 回答