我一直在阅读Wikibooks上的existential section,这就是那里所说的:
首先,forall确实对所有人来说意味着什么。一种思考方式 types是具有该类型的值的集合,例如,Bool是 设置{True,False,⊥}(记住底部,⊥,是每个人的成员 type!),Integer是整数(和底部)的集合,String是集合 所有可能的字符串(和底部),等等。 forall作为一个 这些集合的交叉点。例如,forall a。 a是所有类型的交集,它必须是{⊥},即其唯一值(即元素)是底部的类型(即集合)。
forall
如何作为这些集合的交集?
forall
意味着它可以是来自话语世界的任何价值。在Haskell中它如何被转换为交集?
答案 0 :(得分:4)
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
,元素的类型为b
。 Bool -> 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
我们可以构建任意arity的产品。
那么,如何配合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|
1}} - s相乘,等于|B|^|A|
。因此名称"指数类型"有时用来表示功能。当功能依赖时,我们会回归到某些不同类型的"产品。解释,因为指数公式不再适合。
有了这种理解,我们可以将forall (a :: *). t
解释为索引类型为*
的产品类型和类型为t
的字段,其中a
可能会被提及{ {1}},因此字段类型可能会因t
的选择而异。我们可以通过使Haskell推断a
的某个特定类型来查找字段,从而有效地将该函数应用于类型参数。
请注意,考虑到Haskell类型的潜在数量,此产品具有尽可能多的索引值的字段,这里几乎是无限的。
答案 1 :(得分:3)
您必须在负面或正面背景下查看类型 - 即。无论是在构建过程中还是在使用过程中(有/接收,这在游戏语义学中可能都是最好理解的,但我对它们并不熟悉)。
如果我"给你"类型forall a . a
然后你知道我必须以某种方式构造它。特定构造值具有类型forall a . a
的唯一方法是它可以是一个替代品#34;对于所有"话语世界中的类型 - 当然,这是他们的功能的交集。在理智的语言中,不存在这样的值(Void
),但在Haskell中我们有底。
bottom :: forall a . a
bottom = let a = a in a
另一方面,如果我以某种方式神奇地具有forall a . a
的值并且我尝试使用它然后我们得到相反的效果 - 我可以将其视为<话语世界中所有类型的em> union (这就是你所寻找的)因此我有
absurd :: (forall a . a) -> b
absurd a = a
答案 2 :(得分:3)
forall
如何作为这些集合的交集?
在这里,您可以开始阅读有关Curry-Howard correspondence的内容。简而言之,您可以将类型视为逻辑命题,将语言表达式视为其类型的证明,将值视为普通形式证明< / em>(无法进一步简化的证明)。例如,"Hello world!" :: String
将被视为“"Hello world!"
是命题String
的证明。”
所以现在把forall a. a
视为一个命题。直观地,将此视为对命题变量的二阶量化陈述:“对于所有陈述a
,a
。”它基本上断言所有命题。这意味着如果x
是forall a. a
的证明,那么对于任何命题P
,x
也是P
的证明。因此,由于forall a. a
的证明是证明任何命题的证据,因此必须遵循forall a. a
的证明必须与您将每个命题映射到集合时得到的证据相同它的证据并采取了他们的交集。并且所有这些集合中唯一的正常形式证明(即“值”)是最低的。
另一种看待它的非正式方式是,通用量化就像无限连接(∀x.P(x)
就像P(c0) ∧ P(c1) ∧ ...
)。从模型理论的角度看,连词是交集的; A ∧ B
为真的评估环境集是A
为真的环境与B
为真的环境的交集。