[英]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.