我推荐你使用StandaloneKindSignatures:
..
{-# Language StandaloneKindSignatures #-}
type Id :: k -> k
type Id a = a
type Proxy :: k -> Type
data Proxy a = Proxy
type
PK :: k -> Type
type family
PK a where
PK Int = Char
kind 参数是不可见的,但您可以在类型族PK @Type Int = Char 中显式编写它(需要TypeApplications)。
使用 GADT,您可以编写 Proxy
type Proxy :: k -> Type
data Proxy a where
Proxy :: Proxy @k a
有建议允许在声明头中显示(种类)应用程序:
type Id :: k -> k
type Id @k a = a
type Proxy :: k -> Type
data Proxy @k a = Proxy
type
PK :: k -> Type
type family
PK @k a where
PK @Type Int = Char
并且我们可以在forall-> 的种类中使用“可见的依赖量化”,而不是(隐式)不可见的forall.
type Id :: forall k -> k -> k
type Id k a = a
type Proxy :: forall k -> k -> Type
data Proxy k a = Proxy
type
PK :: forall k -> k -> Type
type family
PK k a where
PK Type Int = Char
Proxy 之间的区别,定义为统一数据类型(非 GADT 或开玩笑:“遗留”语法)或 GADT。除了 k 是
之外,它们是等效的(在旧的 GHC 8.10 上测试)
- (
forall.) 指定= 可以用TypeApplications 指定,但如果不指定会自动推断
- (
forall{}.) inferred = TypeApplications 跳过,不能直接指定
这适用于类型构造函数Proxy 和名为P 的数据构造函数以消除歧义,因为它们都是多态的。 Proxy可以指定Proxy @Nat 42或者根据k的量化推断Proxy 42:
Proxy :: forall (k :: Type). k -> Type
-- or
Proxy :: forall {k :: Type}. k -> Type
并且根据P中的量化,k可以指定P @Nat @42或推断P @42:
P :: forall {k :: Type} (a :: k). Proxy @k a
P :: forall {k :: Type} (a :: k). Proxy a
-- or
P :: forall (k :: Type) (a :: k). Proxy @k a
P :: forall (k :: Type) (a :: k). Proxy a
这给出了几个结果
-
k 在两者中推断:
P @42 :: Proxy 42 (P @42 :: Proxy 42)
data Proxy a = P
--
data Proxy a where
P :: Proxy a
-
k 在
Proxy 中指定但在P (P @42 :: Proxy @Nat 42) 中推断
data Proxy (a :: k) where
P :: Proxy a
--
type Proxy :: k -> Type
data Proxy a where
P :: Proxy a
-
k 在
Proxy 和P (P @Nat @42 :: Proxy @Nat 42) 中指定
data Proxy (a :: k) = P
--
type Proxy :: k -> Type
data Proxy a = P
--
type Proxy :: forall k. k -> Type
data Proxy a = P
--
type Proxy :: forall k. k -> Type
data Proxy (a :: k) = P
--
type Proxy :: k -> Type
data Proxy a where
P :: Proxy @k a
我正在等待对量化和范围界定的许多新的和即将发生的变化尘埃落定,这可能已经过时了。