为什么没有一个“A”;“存在”;Haskell中用于存在量化的关键字?

为什么没有一个“A”;“存在”;Haskell中用于存在量化的关键字?,haskell,Haskell,根据GHC文件,鉴于以下声明: data Foo = forall a. MkFoo a (a -> Bool) | Nil 然后 与以下伪Haskell声明(几乎)同构 MkFoo :: (exists a . (a, a -> Bool)) -> Foo 因此,不需要单独的“Exist”关键字。因为: Haskell程序员可以安全地想到普通的 上面给出的量化类型 但我不确定这意味着什么。有人能解释一下为什么我们可以使用通用量词来表示存在量化吗?如果

根据GHC文件,鉴于以下声明:

data Foo = forall a. MkFoo a (a -> Bool)
           | Nil
然后

与以下伪Haskell声明(几乎)同构

MkFoo :: (exists a . (a, a -> Bool)) -> Foo
因此,不需要单独的“Exist”关键字。因为:

Haskell程序员可以安全地想到普通的 上面给出的量化类型


但我不确定这意味着什么。有人能解释一下为什么我们可以使用通用量词来表示存在量化吗?

如果你看一下数据构造函数的类型,你会注意到我们同样使用
->
来表示产品。例如

(:) :: a -> [a] -> [a]
实际上,这意味着我们正在使用
(:)
a
与类型
[a]
的列表打包在一起,并交付类型
[a]
的列表


在您的示例中,使用
forall
仅仅意味着
MkFoo
作为构造函数,愿意打包任何类型的
a
。当您阅读GHC文档中的
(存在a.(a,a->Bool))->Foo
时,您应该将其视为原始类型
MkFoo
的未复制版本。
(:)
的相应未载波版本将是
(a,[a])->[a]
首先要注意的是,
forall
量词出现在等号的右侧,因此它与数据构造函数(非类型):
MkFoo
相关联。因此,类型
Foo
a
无关

当我们尝试对
Foo
类型的值进行模式匹配时,我们再次遇到
a
。此时,您对
MkFoo
的组件几乎一无所知,只知道它们存在(必须存在用于调用
MkFoo
的类型),并且第一个组件可以用作第二个组件的参数,第二个组件是一个函数:

f :: Foo -> Bool
f (MkFoo val fn) = fn val
在逻辑(古典或直觉)中,公式

(exists x. p x) -> q
forall x. (p x -> q)
是等效的(请注意,
q
不取决于上面的
x
)。这可以用普遍量化来表示存在量化,前提是存在量化位于蕴涵的左侧。(这是一个经典的例子。)

在函数式编程中,也可以实现同样的效果。而不是写作

-- Pseudo-Haskell follows
f :: (exists a. (a, a->Int)) -> Int
f (x,h) = h x
我们可以使用

-- Actual Haskell
f :: forall a. (a, a->Int) -> Int
f (x,h) = h x
因此,我们可以不用存在量化,至少在上述情况下是这样

当存在量化不在箭头的左边时,仍然需要存在量化。比如说,

g :: exists a. (a, a->Int)
g = (2 :: Int, \x -> x+3)
唉,哈斯克尔选择不包括这些类型。很可能,做出这个选择是为了防止已经复杂的类型系统变得过于复杂

尽管如此,Haskell还是得到了存在数据类型,它只需要围绕存在数据类型包装/展开一个构造函数。例如,使用GADT语法,我们可以编写:

data Ex where
  E :: forall a. (a, a->Int) -> Ex
g :: Ex
g = E (2 :: Int, \x -> x+3)
最后,让我补充一点,存在主义也可以通过秩-2类型和延续传递来模拟:

g :: forall r. (forall a. (a, a->Int) -> r) -> r
g k = k (2 :: Int, \x -> x+3)

您能否为所有x添加
(exists x.p x)->q
的派生步骤。(px->q)
是否等效?我很难用经典逻辑定律来解释它。你可以在Haskell中“证明”等价性:
dataex(p:*->*),其中Ex::px->exp
iso1::(exp->q)->(对于所有x.px->q);iso1fa=f(exa)
iso2::(对于所有x.px->q)->(exp->q);iso2 f(Ex a)=f a
。“经典”的证据可以在这个问题的答案中找到。
g :: forall r. (forall a. (a, a->Int) -> r) -> r
g k = k (2 :: Int, \x -> x+3)