GHCI Haskell 不记得命令行中的绑定
GHCI Haskell not remembering bindings in command line
我正在尝试学习 Haskell 但它有点难,因为我的绑定不是从命令行记住的;下面是我的终端的输出。
> let b = []
> b
[]
> 1:b
[1]
> b
[]
我不知道为什么会这样,谁能帮忙。
您希望您的示例做什么?从您介绍的内容来看,我没有看到任何令人惊讶的地方。
当然,这个答案可能会让您感到惊讶,否则您就不会问了。老实说:我可以猜到你在期待什么。如果我是对的,你认为输出将是:
> let b = []
> b
[]
> 1:b
[1]
> b
[1]
我说得对吗?假设我是,那么问题是:为什么不是?
好吧,简短的版本是 "that's not what (:)
does"。相反,(:)
从其参数中创建了一个新列表; x:xs
是一个新列表,其第一个元素是 x
,其余元素与 xs
相同。但它创建了一个 new 列表。这就像 +
如何创建一个新数字,该数字是其参数的总和:是行为
> let b = 0
> b
0
> 1+b
1
> b
0
也很惊讶? (希望不会!)
当然,这就引出了"well, how do I update b
, then?"的下一个问题。这就是 Haskell 显示其真面目的地方:你没有。在Haskell中,一旦一个变量绑定了一个值,这个值就永远不会改变;就好像所有变量和所有数据类型都是 const
(在类 C 语言或最新的 Javascript 标准中)或 val
(在 Scala 中)。
Haskell 的这个 特性——它被称为纯功能——可能是 [=94] 之间最大的区别=] 和每一种主流语言。当您不在所有地方使用可变状态时,您必须考虑以一种非常不同的方式编写程序。
例如,要走得更远一点,您接下来要尝试的事情很可能是这样的:
> 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 并中止。
这是因为let b = 1 : b
定义了一个名为b
的new变量;你还不如写 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 是 非严格的 ,更多通常被称为 lazy – 这可能是 also 和 Haskell 与所有主流语言之间最大的区别。进一步信息,在 Google 或 Stack Overflow 上搜索 "lazy evaluation"。)
所以,最后,我希望您能明白为什么我并不感到惊讶:Haskell 不可能更新变量绑定。所以既然你的定义是let b = []
,那么最后的结果当然还是[]
:-)
我正在尝试学习 Haskell 但它有点难,因为我的绑定不是从命令行记住的;下面是我的终端的输出。
> let b = []
> b
[]
> 1:b
[1]
> b
[]
我不知道为什么会这样,谁能帮忙。
您希望您的示例做什么?从您介绍的内容来看,我没有看到任何令人惊讶的地方。
当然,这个答案可能会让您感到惊讶,否则您就不会问了。老实说:我可以猜到你在期待什么。如果我是对的,你认为输出将是:
> let b = []
> b
[]
> 1:b
[1]
> b
[1]
我说得对吗?假设我是,那么问题是:为什么不是?
好吧,简短的版本是 "that's not what (:)
does"。相反,(:)
从其参数中创建了一个新列表; x:xs
是一个新列表,其第一个元素是 x
,其余元素与 xs
相同。但它创建了一个 new 列表。这就像 +
如何创建一个新数字,该数字是其参数的总和:是行为
> let b = 0
> b
0
> 1+b
1
> b
0
也很惊讶? (希望不会!)
当然,这就引出了"well, how do I update b
, then?"的下一个问题。这就是 Haskell 显示其真面目的地方:你没有。在Haskell中,一旦一个变量绑定了一个值,这个值就永远不会改变;就好像所有变量和所有数据类型都是 const
(在类 C 语言或最新的 Javascript 标准中)或 val
(在 Scala 中)。
Haskell 的这个 特性——它被称为纯功能——可能是 [=94] 之间最大的区别=] 和每一种主流语言。当您不在所有地方使用可变状态时,您必须考虑以一种非常不同的方式编写程序。
例如,要走得更远一点,您接下来要尝试的事情很可能是这样的:
> 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 并中止。
这是因为let b = 1 : b
定义了一个名为b
的new变量;你还不如写 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 是 非严格的 ,更多通常被称为 lazy – 这可能是 also 和 Haskell 与所有主流语言之间最大的区别。进一步信息,在 Google 或 Stack Overflow 上搜索 "lazy evaluation"。)
所以,最后,我希望您能明白为什么我并不感到惊讶:Haskell 不可能更新变量绑定。所以既然你的定义是let b = []
,那么最后的结果当然还是[]
:-)