Variables 我听说Haskell变量是不可变的,但我能够重新分配和更新变量值

Variables 我听说Haskell变量是不可变的,但我能够重新分配和更新变量值,variables,haskell,immutability,mutable,Variables,Haskell,Immutability,Mutable,我听说Haskell变量是不可变的,但我能够重新分配和更新变量值 您正在跟踪,而不是变异。首先,请注意,GHCi语法与Haskell源文件语法并不完全相同。特别是,x=3实际上曾经是非法的: GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help Prelude> x = 3 <interactive>:2:3: parse error on input ‘=’ 相比之下,在Haskell源文件中,let

我听说Haskell变量是不可变的,但我能够重新分配和更新变量值


您正在跟踪,而不是变异。

首先,请注意,GHCi语法与Haskell源文件语法并不完全相同。特别是,
x=3
实际上曾经是非法的:

GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
Prelude> x = 3

<interactive>:2:3: parse error on input ‘=’
相比之下,在Haskell源文件中,
let x=3
本身从未合法过。这只适用于特定环境,即一元
do

因此,有两个嵌套作用域。当您在某个表达式中查找变量时,Haskell总是选择“最近的一个”,即在内部范围内:

main =
   let x = 1
     ┌──
   in│let x = 3
     │in print x
     └─
外部的
x
一点也不被触及,它基本上与内部范围内发生的任何事情无关。如果询问您的文件中是否有可疑内容,编译器实际上会就此发出警告:

$ ghc -Wall wtmpf-file16485.hs 
[1 of 1] Compiling Main             ( wtmpf-file16485.hs, wtmpf-file16485.o )

wtmpf-file16485.hs:3:8: warning: [-Wunused-local-binds]
    Defined but not used: ‘x’
  |
3 |    let x = 1
  |        ^

wtmpf-file16485.hs:3:12: warning: [-Wtype-defaults]
    • Defaulting the following constraint to type ‘Integer’
        Num p0 arising from the literal ‘3’
    • In the expression: 3
      In an equation for ‘x’: x = 3
      In the expression:
        do let x = 1
           let x = 3
           print x
  |
3 |    let x = 1
  |            ^

wtmpf-file16485.hs:4:8: warning: [-Wname-shadowing]
    This binding for ‘x’ shadows the existing binding
      bound at wtmpf-file16485.hs:3:8
  |
4 |    let x = 3
  |        ^

所有这一切的结果是,以这种方式“变异”的变量对使用原始变量的其他函数没有影响。例如:

GHCi, version 8.2.1: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/sagemuej/.ghci
Loaded GHCi configuration from /home/sagemuej/.ghc/ghci.conf
Prelude> let x = 1
Prelude> let info = putStrLn ("x is ="++show x++" right now")
Prelude> x = 3
Prelude> info
x is =1 right now
另一个结果是,试图使用旧值的“更新”的行为非常有趣:

Prelude> let s = "World"
Prelude> s = "Hello"++s
Prelude> s
"HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHell^C

在这里,新的绑定不仅仅是在旧的
s=“World”
前面加上“Hello”。相反,它将
“Hello”
前置到自己的结果值,而结果值又由
“Hello”
前置到。。。以此类推。

不,你不是:你在一个更紧的范围内引入了一个同名的新变量。这是不一样的,因为你可以(实际上不是直接在ghci中,因为这里你基本上是在线构造一个monad),构造一个逃避这个范围的monad,然后它会把outher变量作为值取回来。好的,谢谢你Willem Van OnTemple不要发布文本,比如控制台输出,作为图像--只需直接复制和粘贴文本。这对每个人来说都比较容易。虽然严格来说这是正确的,但我认为你应该扩展这个答案,并对这里发生的事情给出更严格的解释。 3
main =
   let x = 1
   in let x = 3
      in print x
main =
   let x = 1
     ┌──
   in│let x = 3
     │in print x
     └─
$ ghc -Wall wtmpf-file16485.hs 
[1 of 1] Compiling Main             ( wtmpf-file16485.hs, wtmpf-file16485.o )

wtmpf-file16485.hs:3:8: warning: [-Wunused-local-binds]
    Defined but not used: ‘x’
  |
3 |    let x = 1
  |        ^

wtmpf-file16485.hs:3:12: warning: [-Wtype-defaults]
    • Defaulting the following constraint to type ‘Integer’
        Num p0 arising from the literal ‘3’
    • In the expression: 3
      In an equation for ‘x’: x = 3
      In the expression:
        do let x = 1
           let x = 3
           print x
  |
3 |    let x = 1
  |            ^

wtmpf-file16485.hs:4:8: warning: [-Wname-shadowing]
    This binding for ‘x’ shadows the existing binding
      bound at wtmpf-file16485.hs:3:8
  |
4 |    let x = 3
  |        ^

main = do
   let xOuter = 1
   let xInner = 3
   print xInner
GHCi, version 8.2.1: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/sagemuej/.ghci
Loaded GHCi configuration from /home/sagemuej/.ghc/ghci.conf
Prelude> let x = 1
Prelude> let info = putStrLn ("x is ="++show x++" right now")
Prelude> x = 3
Prelude> info
x is =1 right now
Prelude> let s = "World"
Prelude> s = "Hello"++s
Prelude> s
"HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHell^C