当我们enable PolyKinds
时,我们是否知道f a ~ g b
暗示f ~ g
和a ~ b
?
trying to answer another question时,我将问题缩小到仅在启用PolyKinds
时才收到以下错误。
Could not deduce (c1 ~ c)
from the context ((a, c z) ~ (c1 a1, c1 b))
如果polykinded类型应用是单射的,我们可以推导c1 ~ c
如下。
(a, c z) ~ (c1 a1, c1 b)
(a,) (c z) ~ (c1 a1,) (c1 b) {- switch to prefix notation -}
c z ~ c1 b {- f a ~ g b implies a ~ b -}
c ~ c1 {- f a ~ g b implies f ~ g -}
c1 ~ c {- ~ is reflexive -}
在Haskell中,类型应用是单射的。如果是f a ~ g b
,那么f ~ g
和a ~ b
。我们可以通过编译以下来证明这一点
{-# LANGUAGE GADTs #-}
import Control.Applicative
second :: a -> a -> a
second _ = id
typeApplicationIsInjective :: (Applicative f, f a ~ g b) => f a -> g b -> f b
typeApplicationIsInjective fa gb = second <$> fa <*> gb
类型应用程序的类型不是单射的。如果我们考虑以下内容,其类型为(* -> *) -> *
。
newtype HoldingInt f = HoldingInt (f Int)
我们可以问ghci在应用于某种(* -> *) -> *
时是什么样的* -> *
种类,*
> :k HoldingInt
HoldingInt :: (* -> *) -> *
> :k Maybe
Maybe :: * -> *
> :k HoldingInt Maybe
HoldingInt Maybe :: *
这类似* -> *
应用于某种类型的*
> :k Maybe
Maybe :: * -> *
> :k Int
Int :: *
> :k Maybe Int
Maybe Int :: *
因此,借用syntax from KindSignatures
并不是真的,第一组签名意味着第二套签名。
f :: kf, g :: kg, a :: ka, b :: kb, f a :: k, g b :: k
g :: kf, f :: kg, b :: ka, a :: kb
答案 0 :(得分:6)
Polykinded类型的应用从外部是单射的,但在Haskell内部肯定不是单射的。
“来自外部的”injective“我的意思是,只要Refl
类型为f a :~: g b
,就必须是f
等于g
的情况并且a
等于b
,并且因为我们知道不同类型的类型永远不相等,所以种类也必须相同。
问题是GHC只有同类型的等式约束,并且根本没有类型的等式约束。使用强制编码GADT的机制仅存在于类型和提升类型级别。这就是为什么我们不能表达异质平等,以及为什么我们不能推广GADT。
{-# LANGUAGE PolyKinds, GADTs, TypeOperators #-}
data HEq (a :: i) (b :: k) :: * where
HRefl :: HEq a a
-- ERROR: Data constructor ‘HRefl’ cannot be GADT-like in its *kind* arguments
此外,这里有一个GHC的简单例子,不推断注入性:
sym1 :: forall f g a b. f a :~: g b -> g b :~: f a
sym1 Refl = Refl
-- ERROR: could not deduce (g ~ f), could not deduce (b ~ a)
如果我们使用相同类型注释a
和b
,则会检出。
This paper讨论了上述限制以及如何在GHC中消除它们(它们描述了具有统一类型/类型强制和异构等式约束的系统)。
答案 1 :(得分:5)
如果类型级别的应用程序有不同的类型,则这两种类型不能显示为相同。这是证据:
GHC.Prim> () :: ((Any :: * -> *) Any) ~ ((Any :: (* -> *) -> *) Any) => ()
<interactive>:6:1:
Couldn't match kind ‘*’ with ‘* -> *’
Expected type: Any Any
Actual type: Any Any
In the expression:
() :: ((Any :: * -> *) Any) ~ ((Any :: (* -> *) -> *) Any) => ()
In an equation for ‘it’:
it
= () :: ((Any :: * -> *) Any) ~ ((Any :: (* -> *) -> *) Any) => ()
<interactive>:6:7:
Couldn't match kind ‘*’ with ‘* -> *’
Expected type: Any Any
Actual type: Any Any
In the ambiguity check for: Any Any ~ Any Any => ()
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In an expression type signature:
((Any :: * -> *) Any) ~ ((Any :: (* -> *) -> *) Any) => ()
In the expression:
() :: ((Any :: * -> *) Any) ~ ((Any :: (* -> *) -> *) Any) => ()
(即使打开建议的AllowAmbiguousTypes
扩展名也会出现相同的类型检查错误 - 只是没有建议。)
因此,如果两种类型可以显示相等,那么在等式两边的相同结构位置的类型级应用程序具有相同的类型。
如果您希望提供证据而非证据,则需要写下关于Type Checking with Open Type Functions中描述的系统的仔细归纳证明。对图3的检查向我表明,不变的“所有类型的应用程序在〜的两侧都有相同的类型”被保留,虽然我和论文都没有仔细证明这一点,所以它有可能是不是这样。