Haskell 全局变量“;总计”;没有正确更新

Haskell 全局变量“;总计”;没有正确更新,haskell,global-variables,Haskell,Global Variables,我正在做一个赋值,计算列表中所有整数的和。我应该在没有任何标准库函数(标准加法运算符除外)帮助的情况下执行此操作 我想这意味着我不能使用长度我理解这一点,对吧?这会成为一个问题,因为我不知道如何知道何时停止递归函数以遍历数组 输入的a应该处理的是[]和[0-X],其中X是任意整数。这个例子的X值为10,所以不要期望测试任何大的东西 作业中提到应该采用以下格式,但我不确定我是否遵循: sum1 [] = ... sum1 (x:xs) = ... 这是我所知道的。它工作正常,我并不在乎它

我正在做一个赋值,计算列表中所有整数的和。我应该在没有任何标准库函数(标准加法运算符除外)帮助的情况下执行此操作

我想这意味着我不能使用
长度
我理解这一点,对吧?这会成为一个问题,因为我不知道如何知道何时停止递归函数以遍历数组

输入的a应该处理的是
[]
[0-X]
,其中X是任意整数。这个例子的X值为10,所以不要期望测试任何大的东西

作业中提到应该采用以下格式,但我不确定我是否遵循:

sum1 []     = ...
sum1 (x:xs) = ...
这是我所知道的。它工作正常,我并不在乎它是否效率低下。这是我第一次使用Haskell:

iterate_list :: [Int] -> Int -> Int -> IO()
iterate_list func_list index total = do
    if index < length func_list
    then do
        let new_total = total + (func_list !! index)
        let new_index = index + 1
        iterate_list func_list new_index new_total
    else 
        print(total)
        

sum1 :: [Int] -> IO()
sum1 list = do
    if length list < 1
    then do
        print(0)
    else
        iterate_list list 0 0
然而,我现在遇到的问题是
total
返回0,几乎就像它是一个常量一样。我可能是这样编程的,但我不太确定到底发生了什么

根据赋值描述,I无法通过递归函数传递变量来存储该值。我以前也这样做过。是否有人知道是否有一种方法可以将“
total
”变量置于函数之外

total :: Int
total = 0

sum1 :: [Int] -> IO()
sum1 (x:xs) = do
    if xs == []
    then do
        print(total)
    else do
        let total = total + x
        sum1 xs
该代码所述内容:

  • 全局
    total
    是一个常量整数,等于
    0

  • sum1
    获取整数列表并生成不产生结果的IO操作

  • 如果
    sum1
    给出了一个非空列表,则:

    • 如果该列表的尾部为空(即,整个列表有1个元素),则打印全局变量
      total

    • 否则:

      • 创建一个名为
        total
        的新局部变量,隐藏全局变量,并将其定义为
        x
        加上自身(无限循环)

      • 递归调用列表尾部的
        sum1

  • 如果
    sum1
    给出一个空列表,它将抛出一个错误

这表明你的想法非常迫切。不要试图定义一个自底向上的过程来递增地更新总计,直到最终结果为止,您需要考虑如何通过分解输入来计算总计作为一个值。Haskell中的变量是不可变的;当你写
=
时,它意味着相等,从不“分配”或“更新”

首先,
sum1
应该返回
Int
,因为不需要使用
IO
do
表示法

sum1 :: [Int] -> Int
如果要打印应用于某个列表
someList
(例如从
main
)的
sum1
的结果,请在那里使用
print
,即
print(sum1 someList)

接下来,应该根据输入的两种可能情况定义函数:空列表和非空列表

sum1 [] = …

sum1 (x : xs) = …
您需要定义这些情况,以便像
sum1[1,2,3,4]
这样的输入,您可以回忆起它是用于
sum1(1:(2:(3:[]))
的,它可以产生与
1+2+3+4
等价的东西

首先,对于空列表,结果应该是什么?您可以从以下事实推断出这一点:附加在一起的两个列表的总和应该与它们各自的总和相同;也就是说,对于任何列表
xs
ys
,这些表达式应产生相同的结果:

sum1 xs + sum1 ys
sum1 (xs ++ ys)
假设
xs
ys
为空,则不应更改总和:

  • sum1[]+sum1 ys
    =
    sum1([]++ys)
    =
    sum1 ys
  • sum1-xs+sum1[]
    =
    sum1(xs++[])
    =
    sum1-xs
其次,对于非空的情况:您得到一个元素
x::Int
和一个列表
xs::[Int]
,您需要计算这两个元素的总和。例如,给定
[1,2,3,4]
x
设置为
1
xs
[2,3,4]
。假设您已经有了
xs
的总和;这和
x
的结果是什么?您如何获得xs的和?

您不能简单地更新Haskell中的变量。所有值都是不可变的。您应该考虑如何使用递归调用的返回值,而不是简单地调用函数以获得其副作用

你最初问题的暗示是定义

sum [] = ...
sum (x:xs) = ...
首先,非空列表的总和是多少?它必须包含
x
,因此您将向
x
添加一些内容:

sum (x:xs) = x + ...

第二,空列表的总和是多少?虽然为空列表定义一个值可能没有意义,但想想
sum[3]
肯定会返回什么,以及
sum(3:[])==3+…
这一事实。
sum[]
有一个相当简单的定义,几乎由加法的定义决定。

您不需要显式计算列表的长度来计算其所有元素的总和。你的作业给了你很大的暗示;您的代码没有遵循该提示。在提示中写下代码,并填写
。例如,空列表的总和是多少?如果您能够在执行加法之前计算列表的总和,那么非空列表的总和是多少?与其他语言相比,在Haskell中,索引的使用并不多。您应该从递归的角度考虑:空列表的和是什么?如果您拥有非空列表尾部的总和,那么该列表的总和是多少?我认为
(您的类型应该是
sum1::[Int]->Int
;您的函数不需要打印任何内容。如果调用方想要打印总和,可以在
之后进行打印
sum (x:xs) = x + ...