Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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显式forall,带“;“失踪”;lhs上的类型参数_Haskell - Fatal编程技术网

Haskell显式forall,带“;“失踪”;lhs上的类型参数

Haskell显式forall,带“;“失踪”;lhs上的类型参数,haskell,Haskell,我正在阅读的源代码,我偶然发现了下面的一段代码 data BlockedFetch r = forall a. BlockedFetch (r a) (ResultVar a) 并意识到我不完全理解ExplicitForall/存在量化的用法 上面的代码片段在哪些方面与 data BlockedFetch r a = BlockedFetch (r a) (ResultVar a) 为什么我可以“省略”数据声明lhs上的类型参数。不同之处在于,您可以(事实上,这种情况在代码中更进一步)创建一

我正在阅读的源代码,我偶然发现了下面的一段代码

data BlockedFetch r = forall a. BlockedFetch (r a) (ResultVar a)
并意识到我不完全理解
ExplicitForall
/
存在量化的用法

上面的代码片段在哪些方面与

data BlockedFetch r a = BlockedFetch (r a) (ResultVar a)

为什么我可以“省略”数据声明lhs上的类型参数。

不同之处在于,您可以(事实上,这种情况在代码中更进一步)创建一个类型列表
[BlockedFetch request]
,其中单个
BlockedFetch
具有不同的
a
类型(您无法使用
[BlockedFetch请求a]
-此处的
a
必须与整个列表相同。代码片段上方的注释很好地解释了这一点:

-- We often want to collect together multiple requests, but they return
-- different types, and the type system wouldn't let us put them
-- together in a list because all the elements of the list must have the
-- same type. So we wrap up these types inside the 'BlockedFetch' type,
-- so that they all look the same and we can put them in a list.
--
-- When we unpack the 'BlockedFetch' and get the request and the 'ResultVar'
-- out, the type system knows that the result type of the request
-- matches the type parameter of the 'ResultVar', so it will let us take the
-- result of the request and store it in the 'ResultVar'.
在Haxl中发生的大致情况是,您希望有一种从远程存储并行获取一组不同类型的值的方法。您这样做的方法是制作一组
MVar
,其中包含您计划获取的值。然后,在您的代码中,您可以自由使用这些变量。但是,
MVar
块直到它被“填满”


但是,要填充
MVar
,只需要保留对
MVar
的引用和填充方法-因此,在一天结束时,您甚至不需要知道
MVar
将包含的内容的类型。这是一种存在类型-存在某种类型
a
,而
BlockedFetch
>将尝试填充,但会因不同的
BlockedFetch
而有所不同。

请考虑一个更简单的示例:

data ShowBox = forall a. Show a => ShowBox a
读作

data ShowBox = whatever a. Show a => ShowBox a
现在很明显,
ShowBox
可以包含任何类型的值,只要该类型是
Show
的实例

ex :: [ShowBox]
ex = [ShowBox 'a', ShowBox (), ShowBox [1,2,3]]
这样你就可以阅读了

data BlockedFetch r = forall a. BlockedFetch (r a) (ResultVar a)

由于“
BlockedFetch
包含
ra
ResultVar a
,无论
a

如其他人所述,代码中的示例是存在量化的示例,因此与问题中的最后一个示例完全不同

首先要注意的是,现在GADT表示法通常是首选的。GADT表示法中的类型是:

数据阻塞取数器,其中
BlockedFetch::r a->ResultVar a->BlockedFetch r
我们可以显式绑定
a
,如下所示:

数据阻塞取数器,其中
BlockedFetch::对于所有a.r a->ResultVar a->BlockedFetch r
如果我们有自由存在量化,这将同构于以下内容:

数据阻塞取数器,其中
BlockedFetch::(存在a.(RA,ResultVar a))->BlockedFetch r
这与不引入新关键字的愿望相结合,导致了旧的存在量化语法

BlockedFetch::for all r a.r a->ResultVar a->BlockedFetch r
这就是试图用语法传达的内容:

data BlockedFetch r=forall a.BlockedFetch(ra)(ResultVar a)
从这个角度来看,与使用
blocked fetch r a
不同的是,数据构造函数类型的结果中会出现
a
。示意图上,所有a.F a->G
在逻辑上等同于
(存在a.F a)->G
,但显然不是所有a.F a->G a都等同于
(存在a.F a)->G a
,因为后者甚至没有很好的范围

回到

BlockedFetch::for all r a.r a->ResultVar a->BlockedFetch r

如果你不理解存在论,但你确实理解普遍量化,那么你就可以理解这方面的情况。在这里,我们看到有人调用
BlockedFetch
,即使用数据构造函数构建值,可以自由选择他们想要的
a
类型。有人消费,即patt在匹配上,类型为
BlockedFetch R
的值实质上是为所有a.RA->ResultVar a->X编写一个函数
,该函数必须适用于
a
的任何值,即调用该函数的人可以选择
a
,该函数必须使用该选项。

这两种类型完全相同不同。例如,前者允许您拥有具有不同
a
类型的
BlockedFetch
值列表(即类型
[BlockedFetch r]
有效且未提及
a
),而后者则不能,因为类型将是
[BlockedFetch r a]
但是现在所有元素的
a
都必须匹配。关于GADT符号的观点与epsilonhalbe的问题高度相关。由
存在量化
启用的所有
关键字的使用实际上与由
RankNTypes
启用的关键字大不相同,后者是conf的潜在来源usion.GADT表示法使这一区别变得明显。
+1
关于GADT语法,我想不出哪种情况下,存在量化与常规ADT语法相比看起来更好。