{-# 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)
有什么不同? - 为什么
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
(虽然我找不到任何文档)。 在 ghci 中,:t foo1
给出foo1::Bar a => Proxy a -> Proxy a
。 给定任何Proxy a
,其中a
属于Foo
类型,并且是Bar
的实例,它返回Proxy一个
。没有。构造函数
BarProxy
具有 2 级多态类型(forall a.Bar a => Proxy a) -> BarProxy
。 这意味着只有在以下情况下参数p
才可以传递给BarProxy
:p
的 all 类型a
具有Proxy a
类型,它是Bar
的实例>。 如果你想要存在量化的,你可以写data BarProxy = forall a. Bar a => BarProxy (Proxy a)
或
data BarProxy where BarProxy :: forall a. Bar a => Proxy a -> BarProxy
启用
-XGADTs
。让我们打电话吧
BarProxy
类型为forall a。 Bar a => Proxy a -> BarProxy
存在BarProxy
和(forall a.Bar a => Proxy a) -> BarProxy
universalBarProxy
类型。 对于存在性参数,参数p
的类型应为任一Proxy FooA
或Proxy FooB
(通过{a | a 是 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
接受三者中的任何一个,而Universal One 仅接受proxyPoly
。foo2 p = BarProxy (foo1 p)
编译为存在的BarProxy
。
关于haskell - 构造函数内部和构造函数外部 forall 量词的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60558972/