GHCI Haskell不记得命令行中的绑定

som*_*ing -2 binding command-line haskell ghc

我正在尝试学习Haskell,但它有点难,因为我的绑定不会从命令行记住; 我的终端输出如下.

> let b = []
> b
[]
> 1:b
[1]
> b
[]
Run Code Online (Sandbox Code Playgroud)

我不知道为什么这样可以请任何人帮忙.

Ant*_*sky 5

你期望你的榜样做什么?从你所呈现的内容来看,我没有看到任何令人惊讶的结果.


当然,这个答案对你来说可能是令人惊讶的,或者你不会问.而且我会说实话:我可以猜到你的期望.如果我是对的,你认为输出将是:

> let b = []
> b
[]
> 1:b
[1]
> b
[1]
Run Code Online (Sandbox Code Playgroud)

我对吗?假设我,那么问题是:为什么不呢?

嗯,短版本是"那不是什么(:)".相反,(:)从其参数中创建一个新列表; x:xs是一个新的列表,其第一个元素是x,其余的是相同的xs.但它创建了一个列表.这就像+创建一个新数字一样,它是参数的总和:是行为

> let b = 0
> b
0
> 1+b
1
> b
0
Run Code Online (Sandbox Code Playgroud)

也很惊讶?(希望不是!)


当然,这开启了下一个问题"好吧,我如何更新b呢?".而这正是Haskell展现其真实色彩的地方:你没有.在Haskell中,一旦变量绑定到某个值,该值就永远不会改变; 就好像所有变量和所有数据类型const(使用C语言或最新的Javascript标准)或val(在Scala中)一样.

Haskell的这个特性 - 它被称为纯功能 - 可能是Haskell与每一种主流语言之间最大的区别.当你不在任何地方处理可变状态时,你必须考虑以一种非常不同的方式编写程序.

例如,为了更远一点,你很可能会尝试下一件事:

> let b = []
> b
[]
> let b = 1 : b
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您打算在打字时打印出来的是什么b

好吧,记住,变量不会改变!所以答案是:

[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,…
Run Code Online (Sandbox Code Playgroud)

永远 - 或直到你击中控制-C并中止.

这是因为let b = 1 : b定义了一个名为的变量b; 你可能也写过let c = 1 : c.因此,你说" b是一个1后面跟着的列表b"; 因为我们知道什么b是可以代替的,并得到" b是该列表1由后跟1其次是b",等等,直到永远.或者:b = 1 : b所以代替b我们得到b = 1 : 1 : b,然后代替我们得到b = 1 : 1 : 1 : 1 : ….

(Haskell产生无限列表而不是进入无限循环的事实是因为Haskell 是非严格的,更普遍地称为惰性 - 这可能是Haskell与每种主流语言之间的最大区别.有关详细信息,请在Google或Stack Overflow上搜索"延迟评估".)


所以,最后,我希望你能看出为什么我并不感到惊讶:Haskell不可能更新变量绑定.所以,既然你的定义是let b = [],那么当然最后的结果仍然是[]:-)