forall 作为这些集合的交集

Posted

技术标签:

【中文标题】forall 作为这些集合的交集【英文标题】:forall as an intersection over those sets 【发布时间】:2014-08-16 21:12:22 【问题描述】:

我一直在阅读 Wikibooks 上的 existential section,这就是那里所说的:

首先,forall 确实意味着“为所有人”。一种思考方式 types 是具有该类型的值的集合,例如,Bool 是 设置 True, False, ⊥(记住底部,⊥,是每个 类型!),整数是整数的集合(和底部),字符串是集合 所有可能的字符串(和底部),等等。 forall 作为一个 这些集合的交集。例如,forall a。 a是所有类型的交集,必须是⊥,即唯一值(即元素)为bottom的类型(即集合)。

forall 如何作为这些集合的交集?

forall 在形式逻辑中意味着它可以是话语世界中的任何值。在 Haskell 中它是如何被翻译成交集的?

【问题讨论】:

【参考方案1】:

Haskell 的forall-s 可以被视为受限的依赖函数类型,我认为这是在概念上最具启发性的方法,也最适合集合论或逻辑解释。

在依赖语言中,可以绑定函数类型中的参数值,并在返回类型中提及这些值。

-- Idris
id : (a : Type) -> (a -> a)
id _ x = x 

-- Can also leave arguments implicit (to be inferred)
id : a -> a
id x = x

-- Generally, an Idris function type has the form "(x : A) -> F x"
-- where A is a type (or kind/sort, or any level really) and F is 
-- a function of type "A -> Type" 

-- Haskell
id :: forall (a : *). (a -> a)
id x = x 

关键的区别在于 Haskell 只能使用 forall 绑定类型、提升类型和类型构造函数,而依赖语言可以绑定任何东西。

在文献中,依赖函数被称为依赖产品。当它们是函数时,为什么要这样称呼它们?事实证明,我们可以只使用依赖函数来实现 Haskell 的代数积类型。

通常,任何函数a -> b 都可以被视为某些产品的查找函数,其中键的类型为a,元素的类型为bBool -> Int 可以解释为一对Int-s。这种解释对于非依赖函数来说不是很有趣,因为所有的产品字段必须是相同的类型。通过依赖函数,我们的对可以是适当的多态:

Pair : Type -> Type -> Type 
Pair a b = (index : Bool) -> (if index then a else b) 

fst : Pair a b -> a
fst pair = pair True

snd : Pair a b -> b
snd pair = pair False

setFst : c -> Pair a b -> Pair c b
setFst c pair = \index -> if index then c else pair False

setSnd : c -> Pair a b -> Pair a c
setSnd c pair = \index -> if index then pair True else c 

我们在这里恢复了对的所有基本功能。此外,使用Pair,我们可以构建任意数量的产品。

那么,如何与forall-s 的解释联系起来呢?好吧,我们可以对普通产品进行解读,并为它们建立一些直觉,然后尝试将其转移到forall-s。

所以,让我们先看一下普通产品的代数。代数类型被称为代数,因为我们可以通过代数确定它们的值的数量。 Link to detailed explanation. 如果A 具有|A| 值的数量并且B 具有|B| 的值数量,则Pair A B 具有|A| * |B| 的可能值数量。使用总和类型,我们将居民数量相加。由于A -> B 可以被视为具有|A| 字段的产品,其类型均为B,因此A -> B 的居民数量为|A| 的数量|B|-s 相乘,等于@987654346 @。因此,有时用于表示函数的名称“指数类型”。当函数依赖时,我们回退到“在一些不同类型上的乘积”解释,因为指数公式不再适合。

有了这种理解,我们可以将forall (a :: *). t 解释为具有* 类型索引和t 类型字段的产品类型,其中a 可能在t 中提及,因此字段类型可能因a 的选择而异。我们可以通过让 Haskell 为 forall 推断某些特定类型来查找字段,从而有效地将函数应用于类型参数。

请注意,考虑到 Haskell 类型的潜在数量,该产品具有与索引值一样多的字段,这里几乎是无限的。

【讨论】:

【参考方案2】:

您必须在消极或积极的上下文中查看类型,即无论是在构建过程中,还是在使用过程中(拥有/接收,这在 Game Semantics 中可能是最好理解的,但我对它们并不熟悉)。

如果我“给你”一个类型forall a . a,那么你就知道我必须以某种方式构造它。特定构造值具有 forall a . a 类型的唯一方法是,它可以成为话语领域中“所有”类型的替代——当然,这是它们功能的交集。在理智的语言中不存在这样的价值(Void),但在 Haskell 中我们有底。

bottom :: forall a . a
bottom = let a = a in a

另一方面,如果我以某种方式神奇地获得了 forall a . a 的值并且我尝试使用它,那么我们会得到相反的效果——我可以将它视为 中的任何东西话语世界中所有类型的联合(这就是您要寻找的),因此我有

absurd :: (forall a . a) -> b
absurd a = a

【讨论】:

谢谢,所以建筑更像是所有前提的结合? 正在建设中,它的行为方式是这样的,是的。您通常可以将forall a . a 视为无限积((), Int, Bool, Char, Bool + Char, ((), Int, Bool, Char), ...)。为了构建它,您需要拥有所有这些东西,为了消除它,您只需要一个。您也可以将其视为“空”总和。我的Types of Data 帖子可能会有所帮助。 谢谢,你的帖子很有启发性。您在帖子中提到的axis of construction v. use 是什么? (我听说过 x 和 y axix 但不是这个,谷歌搜索也没有帮助) “轴”只是指比较点。您可以考虑两种模式的类型——under constructionunder use。粗略地说,如果您正在编写函数 (a -> b),那么您会将 a 视为 正在使用,而 b 将视为正在建设中。这种变化就是我所说的“构建和使用轴”。 啊,啊,是的!对此感到抱歉。【参考方案3】:

forall 如何作为这些集合的交集?

在这里,您可能会受益于开始阅读有关Curry-Howard correspondence 的一些信息。长话短说,您可以将类型视为逻辑命题,将语言表达式视为其类型的证明,将值视为范式证明(无法进一步简化的证明)。例如,"Hello world!" :: String 将被解读为“"Hello world!" 是命题 String 的证明。”

所以现在将forall a. a 视为一个命题。直观地,将其视为命题变量上的二阶量化陈述:“对于所有陈述aa。”它基本上是在断言所有命题。这意味着如果xforall a. a 的证明,那么对于任何命题Px 也是P 的证明。因此,由于forall a. a 的证明是证明任何命题的证明,那么必须遵循forall a. a 的证明必须与将每个命题映射到它的证明集时得到的相同,并且走了他们的路口。所有这些集合共有的唯一范式证明(即“值”)是底部。

另一种非正式的看待它的方式是,全称量化就像一个无限合取(∀x.P(x) 就像P(c0) ∧ P(c1) ∧ ...)。从模型理论的角度来看,合取是集合交集; A ∧ B 为真的评估环境集是A 为真的环境与B 为真的环境的交集。

【讨论】:

以上是关于forall 作为这些集合的交集的主要内容,如果未能解决你的问题,请参考以下文章

这样讲解集合知识,不怕学生学不好!

[CF1166E] The LCMs Must be Large - 构造

vector/set集合-交集并集差集对称差

Tree

我应该清除每个要在 forall 中使用的 fetch 循环的集合吗? PLSQL 甲骨文

用java编写程序,求集合的并集、交集和差集