Haskell:将整数推送到堆栈实现时的无限列表

Mr.*_*oom 3 stack haskell

我正在尝试实现一个简单的堆栈,但我很困惑为什么当我将一个整数推送到堆栈时会得到一个无限列表。

所有其他功能都按我的预期工作,但我不明白push. 当我尝试为自己分配一个空堆栈时出错,该堆栈已推送如下变量:

? > a = makeStack
? > push 3 a
[3]
? > a
[]
? > a = push 3 a
? > a
[3,3,3,3,3,3,3,3,3,3^CInterrupted.
Run Code Online (Sandbox Code Playgroud)
type Stack a = [a]

makeStack :: Stack a 
makeStack = []

push :: a -> Stack a -> Stack a
push a as = (a:as)
Run Code Online (Sandbox Code Playgroud)

Rob*_*ond 8

Haskell 不允许突变。在源文件中,如果您定义了一个变量a,然后尝试重新分配它,就像您在此处使用 所做的那样a = push 3 a,您将收到编译错误。你不这样做的唯一原因是你在 GHCi 中工作,它允许你重新定义变量 - 这纯粹是为了方便,所以你不必在尝试不同的定义时一直想着新的名字。

而且,重要的是,a = push 3 a不是要给人一种新的价值a基础上,前一个,因为这将是在命令式语言。相反,它是a 根据自身的定义。

这就是为什么你会得到一个无限列表 - 你的定义处理如下:

a = push 3 a
   = 3:a
   = 3:(push 3 a)
   = 3:(3:a)
Run Code Online (Sandbox Code Playgroud)

等等。由于 Haskell 的懒惰,这样的定义没有问题 - 当您要求完整列表时,GHCi 会像这里一样,一次计算一个元素,因此继续打印 3s,直到您告诉它停止。

要获得您想要的内容,您只需输入push 3 a,或者如果您需要为其指定一个名称,只需从 中选择一个不同的名称即可ab = push 3 a其次是b将如您所愿。