Haskell:为什么将变量的尾部重新分配给它自己的变量会出现问题?

lat*_*jiu 1 recursion haskell list freeze

假设您有一个包含以下列表的变量:

Prelude> arr = [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

你也是,

Prelude> arr
[1,2,3,4,5]
Prelude> arr = tail arr
Prelude> arr

Run Code Online (Sandbox Code Playgroud)

为什么编译器现在冻结了?我试图在递归中实现这个代码语句,但这种现象阻止了我的递归正常工作——它不断返回一个空列表错误。

Sil*_*olo 8

在 Haskell 中,变量总是在它自己定义的范围内。你可能想要的是这个

Prelude> arr1 = [1,2,3,4,5]
Prelude> arr1
[1,2,3,4,5]
Prelude> arr2 = tail arr1
Prelude> arr2
[2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

但是当你写的时候arr = tail arr,REPL 忘记了之前的定义,arr并定义了一个新的,它等于它自己的尾巴。然后你做

Prelude> arr
Run Code Online (Sandbox Code Playgroud)

Haskell 出现并将其评估为tail arr,并将tail其参数评估为WHNF,因此要识别tail arr,我们需要知道 的形状arr,当然,tail arr。所以要知道arr,我们需要知道arr。因此,arr底部,一个非终止值。之前的定义无关紧要。

如果您尝试在 Haskell 源文件(与命令行交互环境相反)中执行此操作,则会收到编译器错误,因为在同一范围内重新绑定现有名称是不正确的。这只是 REPL 的一项功能,您可以出于测试目的这样做。

  • 我想说的是,在 GHCi 中重用变量名是可能的,只是不能在新定义中引用旧值。但这是有效的: `> let arr = [1..5]`; `arr`⇒[1,2,3,4,5]; `让 arr = 跟踪它`; `arr`⇒[2,3,4,5] (4认同)