GHCI Haskell不记得命令行中的绑定
我正在尝试学习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
> 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=[]
,那么最终的结果当然仍然是[]
:-),这真的很有帮助,我非常感谢您。刚开始很难,像我这样的人真的很欣赏这种回到基础的东西,我确实试着研究了答案,但是当你真的什么都不懂的时候,文档很难理解。