关于`let 5 = 10`

39 haskell pattern-matching variable-assignment let assignment-operator

如果我说let 5 = 10,为什么5 + 1返回6而不是11

n. *_* m. 53

当你说

let 5 = 10
Run Code Online (Sandbox Code Playgroud)

它不是5的重新定义,它是一种模式匹配,就像你说的那样

foo 5 = undefined
 ... foo 10 ...
Run Code Online (Sandbox Code Playgroud)

如果匹配,模式就会失败.

在let-expressions中,匹配是懒惰的.这意味着匹配仅在评估由其约束的变量时完成.这允许我们写出类似的东西

 let foo = undefined in 10
Run Code Online (Sandbox Code Playgroud)

在表达式中,没有绑定变量,因此模式永远不会匹配.

可以说这种没有变量的模式在let-bindings中没有任何意义,应该由编译器检测,但语言并不禁止它们.

  • 令人放心的是,让`(5,x)=(10,真)在x`中传递`***例外:<交互>:2:5-21:模式(5,x)`无法反驳的模式失败. (6认同)
  • 这是愚蠢的松懈绑定,但不是所有的:例如'only5 XS = [5 | 5 < - xs]`是有道理的(如果你对列表'失败'没问题). (3认同)
  • pigworker:并且`x中的'let(~5,x)=(10,True)返回'True`只是因为我们已明确告诉编译器假设5模式匹配. (2认同)

chi*_*chi 17

基本上,

let 5 = 10 in ...
Run Code Online (Sandbox Code Playgroud)

相当于

case 10 of ~5 -> ...
Run Code Online (Sandbox Code Playgroud)

注意~,这标志着一种懒惰无可辩驳的模式.这是一个匹配所有内容的模式,并将匹配推迟到实际需要某个变量的点.模式中没有变量5,所以什么都没发生.

这个角落的情况很无用,可以说编译器应该在这里发出警告.

为了澄清懒惰模式的含义,请考虑以下事项:

case f 3 of
  (x,y) -> g 10 x y
Run Code Online (Sandbox Code Playgroud)

这里f 3首先进行评估(到WHNF),公开对构造函数.然后x,y绑定到(尚未评估的)对组件.最后,g 10计算,结果应用于x(现在可能需要),然后应用于y(可能导致xy要求).

通过比较,

case f 3 of
  ~(x,y) -> g 10 x y
Run Code Online (Sandbox Code Playgroud)

不是从评估开始f 3.相反x,必然会受到无价值的影响fst (f 3),y并且必然会受到无价值的影响snd (f 3).我们首先从评估开始g 10.然后,我们将其应用于x:这可能导致x需要,触发评估f 3.然后,我们将结果应用于y,导致类似的评估.大部分实施实际上将共享的结果f 3之间x,并y使其计算最多一次.