Haskell PolyKinds 扩展和类型系列
Haskell PolyKinds extension and type families
我在 Haskell 中研究类型族以更深入地了解这个主题,并尝试同时使用多态类型和类型族。
例如,文件的开头有以下语言扩展名(文件中的扩展名比此处显示的更多):
{-# LANGUAGE TypeFamilies,
StandaloneKindSignatures,
RankNTypes,
PolyKinds,
DataKinds,
TypeOperators,
TypeApplications,
KindSignatures,
ScopedTypeVariables,
UndecidableInstances,
MultiParamTypeClasses,
AllowAmbiguousTypes #-}
然后我在类型声明中使用多态类型:
data Proxy (a :: k) = Proxy
效果很好。但当时我试图在定义更丰富的类型族中使用它们:
type family PK (a :: k) :: Type where
PK Int = Char
GHC 抛出错误:
• Expected kind ‘k’, but ‘Int’ has kind ‘*’
• In the first argument of ‘PK’, namely ‘Int’
In the type family declaration for ‘PK’.
有解决办法吗? GHC 版本为 8.10.7。提前感谢您的任何想法和帮助。
我推荐你使用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
之间的区别,定义为统一数据类型(non-GADT 或 tongue-in-cheek:'legacy' 语法)或 GADT。除了 k 是
之外,它们是等效的(在旧的 GHC 8.10 上测试过)
- (
forall.
) specified = 可以用TypeApplications
指定,但如果不指定则自动推断
- (
forall{}.
) inferred = TypeApplications
略过,不能直接指定
这适用于类型构造函数 Proxy
和名为 P
的数据构造函数以消除歧义,因为它们都是多态的。 Proxy
可以指定 Proxy @Nat 42
或推断 Proxy 42
取决于 k
的量化:
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
我正在等待关于量化和范围界定的许多新的和即将发生的变化尘埃落定,这可能已经过时了。
您还差一种语言扩展。如果您也启用了 CUSKs
扩展,那么您所写的内容将如您所愿。
我在 Haskell 中研究类型族以更深入地了解这个主题,并尝试同时使用多态类型和类型族。
例如,文件的开头有以下语言扩展名(文件中的扩展名比此处显示的更多):
{-# LANGUAGE TypeFamilies,
StandaloneKindSignatures,
RankNTypes,
PolyKinds,
DataKinds,
TypeOperators,
TypeApplications,
KindSignatures,
ScopedTypeVariables,
UndecidableInstances,
MultiParamTypeClasses,
AllowAmbiguousTypes #-}
然后我在类型声明中使用多态类型:
data Proxy (a :: k) = Proxy
效果很好。但当时我试图在定义更丰富的类型族中使用它们:
type family PK (a :: k) :: Type where
PK Int = Char
GHC 抛出错误:
• Expected kind ‘k’, but ‘Int’ has kind ‘*’
• In the first argument of ‘PK’, namely ‘Int’
In the type family declaration for ‘PK’.
有解决办法吗? GHC 版本为 8.10.7。提前感谢您的任何想法和帮助。
我推荐你使用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
之间的区别,定义为统一数据类型(non-GADT 或 tongue-in-cheek:'legacy' 语法)或 GADT。除了 k 是
- (
forall.
) specified = 可以用TypeApplications
指定,但如果不指定则自动推断 - (
forall{}.
) inferred =TypeApplications
略过,不能直接指定
这适用于类型构造函数 Proxy
和名为 P
的数据构造函数以消除歧义,因为它们都是多态的。 Proxy
可以指定 Proxy @Nat 42
或推断 Proxy 42
取决于 k
的量化:
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
我正在等待关于量化和范围界定的许多新的和即将发生的变化尘埃落定,这可能已经过时了。
您还差一种语言扩展。如果您也启用了 CUSKs
扩展,那么您所写的内容将如您所愿。