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

GHCI Haskell不记得命令行中的绑定,haskell,command-line,binding,ghc,Haskell,Command Line,Binding,Ghc,我正在尝试学习Haskell,但这有点难,因为命令行中没有记住我的绑定;下面是我的终端的输出 > let b = [] > b [] > 1:b [1] > b [] 我不知道为什么会这样。请任何人帮忙。您希望您的示例做什么?从你介绍的情况来看,我没有看到任何令人惊讶的事情 当然,这个答案可能会让你感到惊讶,否则你就不会问了。老实说,我能猜出你在期待什么。如果我是对的,您认为输出将是: > let b = [] > b [] > 1:b [1] &g

我正在尝试学习Haskell,但这有点难,因为命令行中没有记住我的绑定;下面是我的终端的输出

> let b = []
> b
[]
> 1:b
[1]
> b
[]

我不知道为什么会这样。请任何人帮忙。

您希望您的示例做什么?从你介绍的情况来看,我没有看到任何令人惊讶的事情


当然,这个答案可能会让你感到惊讶,否则你就不会问了。老实说,我能猜出你在期待什么。如果我是对的,您认为输出将是:

> let b = []
> b
[]
> 1:b
[1]
> b
[1]
我说得对吗?如果我是,那么问题是:为什么不是

嗯,简短的版本是“这不是
(:)
所做的”。相反,
(:)
用它的参数创建一个新列表
x:xs
是一个新列表,其第一个元素是
x
,其余元素与
xs
相同。但它创建了一个新的列表。这就像
+
如何创建一个新的数字,它是它的参数之和:是行为吗

> let b = 0
> b
0
> 1+b
1
> b
0
也令人惊讶吗?(希望不是!)


当然,这打开了下一个问题:“那么,我如何更新
b
?”。这就是Haskell展示其真实面目的地方:你没有。在Haskell中,一旦变量绑定到某个值,该值就永远不会改变;这就好像所有变量和所有数据类型都是
const
(在C语言或最新的Javascript标准中)或
val
(在Scala中)

Haskell的这一特性——被称为纯粹的功能性——可能是Haskell与所有主流语言之间最大的区别。当您不在任何地方使用可变状态时,您必须考虑以非常不同的方式编写程序

例如,若要走得更远一点,很可能您将尝试的下一件事情如下所示:

> let b = []
> b
[]
> let b = 1 : b
在这种情况下,当您键入
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,…
永远–或者直到您点击control-C并中止

这是因为
让b=1:b
定义一个名为
b
的新变量;您还不如编写
让c=1:c
。因此,您的意思是“
b
是一个列表,它是
1
,后跟
b
”;既然我们知道了
b
是什么,我们可以替换并得到“
b
是一个列表,它是
1
,然后是
b
”,以此类推。或者:
b=1:b
,因此替换
b
我们得到
b=1:1:b
,然后替换我们得到
b=1:1:1:…

(事实上,Haskell产生了一个无限列表,而不是进入无限循环,这是因为Haskell不严格,更普遍地被称为懒惰——这可能也是Haskell和所有主流语言之间最大的区别。有关更多信息,请搜索“懒惰评估”在Google或堆栈溢出上。)



所以,最后,我希望您能明白我为什么不感到惊讶:Haskell不可能更新变量绑定。既然您的定义是
让b=[]
,那么最终的结果当然仍然是
[]
:-)

,这真的很有帮助,我非常感谢您。刚开始很难,像我这样的人真的很欣赏这种回到基础的东西,我确实试着研究了答案,但是当你真的什么都不懂的时候,文档很难理解。