Haskell:将整数推送到堆栈实现时的无限列表 [英] Haskell : Infinite list when integer is pushed to stack implementation
问题描述
我正在尝试实现一个简单的堆栈,但我很困惑为什么当我将一个整数压入堆栈时会得到一个无限列表.
I'm trying to implement a simple Stack but I'm confused as to why I get an infinite list when I push an integer to the stack.
所有其他功能都按我的预期工作,但我不明白 push
的问题.当我尝试将一个空堆栈分配给已推送如下变量的自身时,它会出错:
All of the other functions work as I expect them but I don't understand the problem with push
. It goes wrong when I try to assign an empty stack to itself that has pushed a variable like the following:
λ > a = makeStack
λ > push 3 a
[3]
λ > a
[]
λ > a = push 3 a
λ > a
[3,3,3,3,3,3,3,3,3,3^CInterrupted.
type Stack a = [a]
makeStack :: Stack a
makeStack = []
push :: a -> Stack a -> Stack a
push a as = (a:as)
推荐答案
Haskell 不允许突变.在源文件中,如果您定义一个变量 a
然后尝试重新分配它,就像您在此处使用 a = push 3 a
所做的那样,您会得到一个编译错误.您不这样做的唯一原因是您在 GHCi 中工作,它确实允许您重新定义变量 - 这纯粹是一种方便,因此您不必在尝试不同的定义时不断思考新名称.
Haskell does not allow mutation. In a source file, if you define a variable a
and then attempt to reassign it, as you do here with a = push 3 a
, you would get a compilation error. The only reason you don't is that you are working in GHCi, which does allow you to redefine variables - this is purely a convenience so you don't have to keep on thinking up new names while experimenting with different definitions.
而且,至关重要的是,a = push 3 a
不是基于前一个值给 a
一个新值,因为它会使用命令式语言.相反,它是a
就其自身而言的定义.
And, crucially, a = push 3 a
is not giving a new value to a
based on the previous one, as it would be in an imperative language. Instead, it is a definition of a
in terms of itself.
这就是你得到一个无限列表的原因 - 你的定义被处理如下:
That's why you get an infinite list - your definition is processed as follows:
a = push 3 a
= 3:a
= 3:(push 3 a)
= 3:(3:a)
等等.由于 Haskell 的懒惰,这样的定义没有问题 - 当您要求完整列表时,GHCi 会像这里一样一次简单地计算一个元素,因此会一直打印 3 秒,直到您告诉它停止.
and so on. Because of Haskell's laziness, there's no problem with a definition like this - GHCi will, when you ask for the full list, as here, simply calculate one element at a time, and therefore keep printing 3s until you tell it to stop.
要获得您想要的,您只需键入 push 3 a
,或者如果您需要为其指定名称,只需从 a
中选择一个不同的名称.b = push 3 a
后跟 b
将按照您的预期运行.
To get what you want, you need to either just type push 3 a
, or if you need to assign it a name, simply choose a different name from a
. b = push 3 a
followed by b
will behave as you expect.
这篇关于Haskell:将整数推送到堆栈实现时的无限列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!