[英]Difference between forall quantifier inside a constructor and outside a constructor
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}
import Data.Proxy
data Foo = FooA | FooB
class Bar (a :: k) where
bar :: Proxy a -> Int
instance Bar FooA where
bar _ = 1
instance Bar FooB where
bar _ = 2
foo1 :: forall (a :: Foo). Proxy a -> (Bar a => Proxy a)
foo1 p = p
data BarProxy = BarProxy (forall a. Bar a => Proxy a)
foo2 :: forall (a :: Foo). Proxy a -> BarProxy
foo2 p = BarProxy (foo1 p)
main = print "Hello World"
在这段代码中:
foo1
,给定任何Proxy a
,其中a
是Foo
,返回一个Proxy a
使得a
具有Bar
的实例?BarProxy
构造函数不接受任何Proxy a
,其中a
有一个Bar
实例? 和data BarProxy = forall a. BarProxy (Bar a => Proxy a)
有什么区别data BarProxy = forall a. BarProxy (Bar a => Proxy a)
data BarProxy = forall a. BarProxy (Bar a => Proxy a)
?foo2 p = BarProxy (foo1 p)
失败并出现以下错误?Test6.hs:27:20: error:
• Couldn't match type ‘a1’ with ‘a’
‘a1’ is a rigid type variable bound by
a type expected by the context:
forall (a1 :: Foo). Bar a1 => Proxy a1
at Test6.hs:27:10-26
‘a’ is a rigid type variable bound by
the type signature for:
foo2 :: forall (a :: Foo). Proxy a -> BarProxy
at Test6.hs:26:1-46
Expected type: Proxy a1
Actual type: Proxy a
• In the first argument of ‘BarProxy’, namely ‘(foo1 p)’
In the expression: BarProxy (foo1 p)
In an equation for ‘foo2’: foo2 p = BarProxy (foo1 p)
• Relevant bindings include
p :: Proxy a (bound at Test6.hs:27:6)
foo2 :: Proxy a -> BarProxy (bound at Test6.hs:27:1)
|
27 | foo2 p = BarProxy (foo1 p)
| ^^^^^^
不。我的理解是foo1
的签名与forall (a :: Foo). Bar a => Proxy a -> Proxy a
forall (a :: Foo). Bar a => Proxy a -> Proxy a
(虽然我找不到任何文件)。 在 ghci 中, :t foo1
给出foo1 :: Bar a => Proxy a -> Proxy a
。 给定任何Proxy a
,其中a
是Foo
类型和Bar
一个实例,它返回Proxy a
。
不。构造函数BarProxy
具有 rank-2 多态类型(forall a. Bar a => Proxy a) -> BarProxy
。 这意味着只有当p
具有类型Proxy a
的所有类型a
它是Bar
的实例)时,参数p
才能传递给BarProxy
。 如果你想要存在量化的一个,你可以写
data BarProxy = forall a. Bar a => BarProxy (Proxy a)
或者
data BarProxy where BarProxy :: forall a. Bar a => Proxy a -> BarProxy
启用-XGADTs
。
让我们调用forall a. Bar a => Proxy a -> BarProxy
类型的BarProxy
forall a. Bar a => Proxy a -> BarProxy
forall a. Bar a => Proxy a -> BarProxy
存在性BarProxy
和类型(forall a. Bar a => Proxy a) -> BarProxy
通用BarProxy
。 为存在一个,参数p
的类型应该是任何Proxy FooA
或Proxy FooB
(存在上定量比{a | a is an instance of Bar} = {FooA,FooB}
另一方面,对于通用的, p
应该同时具有Proxy FooA
和Proxy FooB
(在同一集合上普遍量化)。 让我们考虑下面的三个代理。
proxyFooA :: Proxy FooA proxyFooA = Proxy proxyFooB :: Proxy FooB proxyFooB = Proxy proxyPoly :: forall a. Proxy a proxyPoly = Proxy
Existential BarProxy
接受三者中的任何一个,而通用proxyPoly
只接受proxyPoly
。
foo2 p = BarProxy (foo1 p)
为存在的BarProxy
编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.