关于“让5 = 10”
如果我说let 5 = 10
,为什么5 + 1
返回6
而不是11
?
当你说
let 5 = 10
这不是对5的重新定义,而是一种模式匹配,当你说的时候会发生同样的情况
foo 5 = undefined ... foo 10 ...
如果匹配,模式就会失败。
在letexpression式中,匹配是懒惰的。 这意味着匹配只在被它所绑定的variables进行评估时完成。 这使我们能够写出类似的东西
let foo = undefined in 10
在你的expression式中,没有variables被绑定,所以模式永远不会匹配。
可以说这样没有variables的模式在绑定中是没有意义的,应该由编译器来检测,但是这种语言并不禁止它们。
基本上,
let 5 = 10 in ...
相当于
case 10 of ~5 -> ...
请注意~
,这标志着一个懒惰 ,或无可争辩的模式 。 这是一个匹配所有事物的模式,并将匹配推迟到实际需要某个variables的点。 模式5
中没有variables,所以什么都没有发生。
这个angular落案例是无用的,可以说编译器应该在这里发出警告。
为了澄清懒惰模式的含义,请考虑这一点:
case f 3 of (x,y) -> g 10 xy
这里f 3
首先被评估(对WHNF),暴露了对构造函数。 然后, x,y
绑定到(尚未评估的)对组件。 最后,计算g 10
,结果应用于x
(现在可能需要),然后应用于y
(这可能导致x
或y
被要求)。
通过对比,
case f 3 of ~(x,y) -> g 10 xy
不是从评估f 3
开始的。 相反, x
被绑定到未评估的fst (f 3)
而y
被绑定到未被评估的snd (f 3)
。 我们从评估g 10
开始。 然后,我们将它应用于x
:这可能导致x
被要求,引发f 3
的评估。 然后,我们将结果应用于y
,导致类似的评估。 大多数实现将实际上共享 x
和y
之间的f 3
的结果,以便最多计算一次。
正如@nm所说,你是模式匹配。 这里有些例子。
模式匹配可以成功
Prelude> let (a, 10) = (15, 10) in a 15
或失败。
Prelude> let (a, 10) = (15, 15) in a *** Exception: <interactive>:5:5-22: Irrefutable pattern failed for pattern (a, 10)
由于Haskell是懒惰的,如果你不使用结果值,你的代码将会成功。 这基本上是你在做什么:
Prelude> let (a, 10) = (15, 15) in "Something else" "Something else"
请注意,types仍然需要检查:
Prelude> let (a, 10, 999) = (15, 15) in "Something else" <interactive>:7:20: error: • Couldn't match expected type '(t, Integer, Integer)' with actual type '(Integer, Integer)' • In the expression: (15, 15) In a pattern binding: (a, 10, 999) = (15, 15) In the expression: let (a, 10, 999) = (15, 15) in "Something else" • Relevant bindings include a :: t (bound at <interactive>:7:6)