Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 什么是谓词性?_Haskell_Type Theory - Fatal编程技术网

Haskell 什么是谓词性?

Haskell 什么是谓词性?,haskell,type-theory,Haskell,Type Theory,我对Haskell禁止的类型有相当不错的直觉,认为它是“非指示性的”:即在类型构造函数的参数中出现一个forall,而不是->。但什么是预测性呢?什么使它重要?它与“谓词”一词有什么关系?这些类型系统的中心问题是:“您能用中的多态类型替换类型变量吗?”。表语型系统是一个毫无意义的学者,回答“绝对不是”,而非表语型系统是你的无忧无虑的伙伴,他认为这听起来很有趣,有什么可能出错 现在,Haskell把讨论搞得有点混乱,因为它认为多态性应该是有用的,但不可见的。因此,在这篇文章的其余部分,我将用哈斯克

我对Haskell禁止的类型有相当不错的直觉,认为它是“非指示性的”:即在类型构造函数的参数中出现一个
forall
,而不是
->
。但什么是预测性呢?什么使它重要?它与“谓词”一词有什么关系?

这些类型系统的中心问题是:“您能用中的多态类型替换类型变量吗?”。表语型系统是一个毫无意义的学者,回答“绝对不是”,而非表语型系统是你的无忧无虑的伙伴,他认为这听起来很有趣,有什么可能出错

现在,Haskell把讨论搞得有点混乱,因为它认为多态性应该是有用的,但不可见的。因此,在这篇文章的其余部分,我将用哈斯克尔方言写作,在这里,不仅允许而且必须使用
forall
。通过这种方式,我们可以区分类型
a
,它是一种单态类型,从稍后定义的类型环境中提取其值,以及类型
。a
,这是一种较难居住的多态类型。我们还将允许
forall
几乎在类型中的任何地方运行——正如我们将看到的,GHC将其类型语法限制为“快速失效”机制,而不是技术要求

假设我们已经告诉编译器
id::for all a。a->a
。我们能否稍后要求使用
id
,就好像它有类型
(对于所有b.b)->(对于所有b.b)
?非指示类型系统对此没有问题,因为我们可以将
id
的类型中的量词实例化为
for all b。b
,并将所有b替换为
。b
用于
a
结果中的所有位置。谓词类型系统对此更为谨慎:只允许使用单态类型。(因此,如果我们有一个特定的
b
,我们可以编写
id::b->b

关于<代码>[]也有类似的故事::对于所有a。[a] 和
(:)::对于所有a。a->[a]->[a]
。虽然你的无忧无虑的伙伴可能对
[]:[forall b.b]
(:):(forall b.b)->[forall b.b]->[forall b.b]
没什么问题,但预测性的学校妈妈却不是。事实上,从仅有的两个列表构造函数中可以看出,如果不将其构造函数中的类型变量实例化为多态值,则无法生成包含多态值的列表。因此,尽管在我们的哈斯克尔方言中允许使用类型
[forall b.b]
,但这并不是真正明智的做法——这种类型没有(终止)术语。这促使GHC决定抱怨,如果你甚至想到这样一种类型——这是编译器告诉你“不要麻烦”的方式*

那么,是什么让校长这么严格呢?和往常一样,答案是保持类型检查和类型推断的可行性。非指示性类型的类型推断是正确的。类型检查,但它非常复杂,没有人想维护它

另一方面,一些人可能会反对GHC对某些似乎需要非指示性的类型非常满意:

> :set -Rank2Types
> :t id :: (forall b. b) -> (forall b. b)
{- no complaint, but very chatty -}
事实证明,一些稍微受限的非指示性版本并不太糟糕:具体来说,类型检查更高级别的类型(当类型变量只是
(>)
的参数时,允许用多态类型替换类型变量)相对简单。你确实会失去等级2以上的类型推断,以及等级1以上的主要类型,但有时更高等级的类型正是医生所要求的

不过,我不知道这个词的词源

*您可能想知道您是否可以这样做:

data FooTy a where
     FooTm :: FooTy (forall a. a)
然后你会得到一个术语(
FooTm
),它的类型有一些多态性作为除
(>)
(即,
FooTy
)之外的其他变量,你不必跨学校去做,因此“将非
(>)
的东西应用到多态类型上”的信念是没有用的,因为你无法使它们成为多态类型将被宣告无效。GHC不允许您编写
FooTy
,我承认我不确定限制是否有原则上的原因


(几年后快速更新:
FooTm
仍然不好有一个很好的原则性原因。即,在GHC中实现GADT的方式是通过类型相等,因此
FooTm
的扩展类型实际上是
FooTm::forall a.(a~ forall b.b)=>FooTy a
。因此,要实际使用
FooTm
,确实需要用多态类型实例化一个类型变量。感谢Stephanie Weirich向我指出这一点。)

让我就“词源”问题补充一点,因为@DanielWagner的另一个答案涵盖了大部分技术基础

类似于
A
的谓词是
A->Bool
。现在谓词逻辑在某种意义上可以对谓词进行推理——因此,如果我们有一些谓词
P
,我们可以讨论,对于给定的
a
P(a)
,现在在“谓词逻辑”(如一阶逻辑)中,我们也可以说
∀A.P(a)
。所以我们可以量化变量,讨论谓词在这些事情上的行为

现在,反过来说,如果谓词应用到的所有事物都是在它之前引入的,那么我们说语句是谓词的。因此,语句是“基于”已经存在的事物的。反过来,如果一个语句在某种意义上可以通过它的“引导”来指代它自己,那么它就是非指示性的

因此,在上面的
id
示例中,我们发现我们可以给
id
指定一个类型,这样它就可以将
id
类型的某个对象转换为
id
类型的另一个对象。所以现在我们可以给一个函数一个类型,其中一个量化变量(由
为所有a.
引入)可以“扩展”为与整个函数本身相同的类型