繁体   English   中英

Haskell显式forall在lhs上有“缺失”类型参数

[英]Haskell explicit forall with “missing” type parameter on lhs

我正在阅读haxl-Haxl的源代码.Core我发现了以下代码

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

并意识到我并不完全理解ExplicitForall / ExistentialQuantification的用法。

上面的代码片段在哪些方面有所不同

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

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

正如其他人所提到的,代码中的示例是存在量化的示例,因此与问题中的最终示例完全不同。

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

data BlockedFetch r where
    BlockedFetch :: r a -> ResultVar a -> BlockedFetch r

我们可以明确地绑定a如下:

data BlockedFetch r where
    BlockedFetch :: forall a. r a -> ResultVar a -> BlockedFetch r

如果我们有免费的存在量化,这将与以下同构:

data BlockedFetch r where
    BlockedFetch :: (exists a. (r a, ResultVar a)) -> BlockedFetch r

这与不引入新关键字的愿望相结合,导致了旧的ExistentialQuantification语法。 BlockedFetch数据构造函数具有类型

BlockedFetch :: forall r a. r a -> ResultVar a -> BlockedFetch r

这就是尝试与语法沟通的内容:

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

从这个角度看,与BlockedFetch ra的不同之处在于,数据构造函数类型的结果会出现a 示意性地, forall a. F a -> G forall a. F a -> G在逻辑上等同于(exists a. F a) -> G ,但显然不是forall a. F a -> G a的情况forall a. F a -> G a forall a. F a -> G a相当于(exists a. F a) -> G a因为后者甚至没有良好的范围。

回到

BlockedFetch :: forall r a. r a -> ResultVar a -> BlockedFetch r

如果你不了解存在感,但你确实理解了普遍的量化,那么你就可以理解这是怎么回事。 在这里,我们看到,有人 BlockedFetch ,即建设一个值与数据的构造,可以自由地选择他们想要哪个类型的a 消费 (即模式匹配) BlockedFetch R类型的BlockedFetch R实际上是在写一个函数forall a. R a -> ResultVar a -> X forall a. R a -> ResultVar a -> X和功能必须努力的任何a ,即调用该函数就可以选择的人a和这个功能必须与选择工作。

区别在于你可以(实际上这在代码中稍微发生)制作一个类型[BlockedFetch request]的列表,其中各个BlockedFetch具有不同a类型(你不能用[BlockedFetch request 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

现在很明显,只要此类型是Show的实例, ShowBox就可以包含任何类型的值。 例如

ex :: [ShowBox]
ex = [ShowBox 'a', ShowBox (), ShowBox [1,2,3]]

所以你可以阅读

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

因为“ BlockedFetch包含一个raResultVar a for for a ”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM