集合推导与量词 ∀ ∃
集合与逻辑是一体两面。谓词(predicate) 是对每个对象或真或假的条件,本身不是命题(见命题的判定);把它交给不同的机制,就得到不同的东西。交给集合推导 ,得到一个子集;交给量词,得到一个命题。
1 · 谓词的三种用法
同一个谓词有三种用法,产出物的类型各不相同。代入一个具体对象 , 是一个命题,有真假。用它作筛选条件, 是 的一个子集,没有真假。用量词约束它, 与 又是命题,各有真假。
三者由同一个真值集合 串起来: 为真即 ; 为真即 ; 为真即 。存在命题的证明只需给出一个见证( 的任一元素),全称命题的否证只需给出一个反例( 的任一元素)——两者的不对称,源头就是「非空」与「等于全集」这两个条件的不对称。
2 · 量词与否定的对偶
定理 2.1(量词否定) 与 等价; 与 等价。
用真值集合读一遍即是显然的: 说 , 说 ,二者是同一句话。这与De Morgan 律是同一条对偶——量词是遍历全集的合取与析取,否定进去时把 与 对调,正如它把 与 对调。
实用价值在于「否定一个命题」有了机械做法:把否定符号逐层推进去,每穿过一个量词就对调一次,最后只否定最内层的谓词。「所有连续函数都可导」的否定不是「所有连续函数都不可导」,而是「存在一个连续函数不可导」。
3 · 空集与量词次序
警示 · 全集为空时两个量词都退化,且退化方向相反: 恒真( 自动成立), 恒假( 不可能非空)。前者叫 vacuous truth,「所有」没有对象可反驳。 恒成立正是它的一个实例(见包含的边界)。
另一处是次序。 与 相邻时不可交换: 允许 随 而变, 要求一个 对所有 通用,后者严格更强。取 、 为「 是 的倍数」:前者为真,取 即可;后者为假,因为通用的 必须是 到 的公倍数,而最小的那个是 ,早已跑出 。
集合推导落到代码里就是 filter,两个量词就是 some 与 every,它们对空数组的取值恰好复刻上面那条警示:[].every(() => false) 为 true,[].some(() => true) 为 false。不过这个类比只在数组稠密时成立。every
与 some 会跳过 hole:长度为
的稀疏数组 [ , , , ] 上 every(() => false) 仍返回 true,some(() => true) 返回 false——谓词一次也没被调用。[1, , 3].every 实测只访问到 1 与 3 两个元素,而 length 是 3(node
v26.6.0)。也就是说这两个方法量词化的全集是「有值的下标」,不是 0 到 length - 1;把稀疏数组当作一个
元素的全集来推理会得到假结论。
4 · 参考文献
- Quantifier (logic). Wikipedia. 全称与存在量词的语义,以及量词次序不可交换。https://en.wikipedia.org/wiki/Quantifier_(logic)
- Set-builder notation. Wikipedia. 集合推导的记法与分离公理。https://en.wikipedia.org/wiki/Set-builder_notation
- Vacuous truth. Wikipedia. 空全集上全称命题为真的约定及其理由。https://en.wikipedia.org/wiki/Vacuous_truth
- Array.prototype.every. ECMA-262. 遍历时跳过缺失下标的规定。https://tc39.es/ecma262/#sec-array.prototype.every