定义类型同义词 (GHC) 的类型同义词时出现奇怪的错误
Weird Error When Defining a Type Synonym of a Type Synonym (GHC)
背景
我在 Haskell (GHC) 中编写了以下代码:
{-# LANGUAGE
NoImplicitPrelude,
TypeInType, PolyKinds, DataKinds,
ScopedTypeVariables,
TypeFamilies
#-}
import Data.Kind(Type)
data PolyType k (t :: k)
type Wrap (t :: k) = PolyType k t
type Unwrap pt = (GetType pt :: GetKind pt)
type family GetType (pt :: Type) :: k where
GetType (PolyType k t) = t
type family GetKind (pt :: Type) :: Type where
GetKind (PolyType k t) = k
这段代码的目的是允许我将任意种类的类型包装成单一种类(即Type
)的类型(即PolyType
),然后反转过程(即打开包装)稍后。
问题
我想为 Unwrap
定义一个类似于以下内容的类型同义词:
type UnwrapSynonym pt = Unwrap pt
但是,上述定义会产生以下错误(GHC 8.4.3):
* Invalid declaration for `UnwrapSynonym'; you must explicitly
declare which variables are dependent on which others.
Inferred variable kinds: pt :: *
* In the type synonym declaration for `UnwrapSynonym'
这个错误是什么意思?有没有办法绕过它来定义 UnwrapSynonym
?
我一直在做什么
到目前为止,我解决这个问题的方法基本上是手动内联 Uwrap
我想定义的任何 high-order 类型的同义词,但这感觉很糟糕,我希望有更好的方法.
不幸的是,我对 GHC 的内部工作原理还不够了解,甚至不了解问题所在,更不用说解决问题了。
我相信我对我正在使用的扩展程序(例如 TypeInType
和 PolyKinds
)的工作方式有很好的理解,但显然还不够深入,无法理解这个错误。此外,我无法找到解决类似问题的资源。部分原因是我不知道如何简洁地描述它,这也导致很难为这个问题想出一个好的标题。
这个错误是相当迟钝的,但我认为它想说的是 GHC 已经注意到 UnwrapSynonym
的类型是依赖的,forall (pt :: Type) -> GetKind pt
,它希望你明确地注释依赖:
type UnwrapSynonym pt = (Unwrap pt :: GetKind pt)
之所以要告诉它 "which variables are dependent on which others" 是因为这个错误也可能会弹出,例如这种情况:
data Nat = Z | S Nat
data Fin :: Nat -> Type where
FZ :: Fin (S n)
FS :: Fin n -> Fin (S n)
type family ToNat (n :: Nat) (x :: Fin n) :: Nat where
ToNat (S n) FZ = Z
ToNat (S n) (FS x) = S (ToNat n x)
type ToNatAgain n x = ToNat n x -- similar error
ToNatAgain
应该有种类forall (n :: Nat) -> Fin n -> Nat
,但是变量x
的类型取决于变量n
的类型。 GHC 希望对其进行显式注释,因此它告诉我告诉它哪些变量依赖于哪些其他变量,并且它为我提供了它推断出的变量类型以帮助实现这一点。
type ToNatAgain (n :: Nat) (x :: Fin n) = ToNat n x
在你的例子中,依赖关系在 return 类型和参数类型之间。根本原因是相同的,但错误消息显然不是根据您的情况设计的,并且不适合。您应该提交错误报告。
顺便说一句,您真的需要单独的 Unwrap
和 GetType
吗?为什么不让 GetType
依赖?
type family GetType (pt :: Type) :: GetKind pt where
GetType (PolyType k t) = t
背景
我在 Haskell (GHC) 中编写了以下代码:
{-# LANGUAGE
NoImplicitPrelude,
TypeInType, PolyKinds, DataKinds,
ScopedTypeVariables,
TypeFamilies
#-}
import Data.Kind(Type)
data PolyType k (t :: k)
type Wrap (t :: k) = PolyType k t
type Unwrap pt = (GetType pt :: GetKind pt)
type family GetType (pt :: Type) :: k where
GetType (PolyType k t) = t
type family GetKind (pt :: Type) :: Type where
GetKind (PolyType k t) = k
这段代码的目的是允许我将任意种类的类型包装成单一种类(即Type
)的类型(即PolyType
),然后反转过程(即打开包装)稍后。
问题
我想为 Unwrap
定义一个类似于以下内容的类型同义词:
type UnwrapSynonym pt = Unwrap pt
但是,上述定义会产生以下错误(GHC 8.4.3):
* Invalid declaration for `UnwrapSynonym'; you must explicitly
declare which variables are dependent on which others.
Inferred variable kinds: pt :: *
* In the type synonym declaration for `UnwrapSynonym'
这个错误是什么意思?有没有办法绕过它来定义 UnwrapSynonym
?
我一直在做什么
到目前为止,我解决这个问题的方法基本上是手动内联 Uwrap
我想定义的任何 high-order 类型的同义词,但这感觉很糟糕,我希望有更好的方法.
不幸的是,我对 GHC 的内部工作原理还不够了解,甚至不了解问题所在,更不用说解决问题了。
我相信我对我正在使用的扩展程序(例如 TypeInType
和 PolyKinds
)的工作方式有很好的理解,但显然还不够深入,无法理解这个错误。此外,我无法找到解决类似问题的资源。部分原因是我不知道如何简洁地描述它,这也导致很难为这个问题想出一个好的标题。
这个错误是相当迟钝的,但我认为它想说的是 GHC 已经注意到 UnwrapSynonym
的类型是依赖的,forall (pt :: Type) -> GetKind pt
,它希望你明确地注释依赖:
type UnwrapSynonym pt = (Unwrap pt :: GetKind pt)
之所以要告诉它 "which variables are dependent on which others" 是因为这个错误也可能会弹出,例如这种情况:
data Nat = Z | S Nat
data Fin :: Nat -> Type where
FZ :: Fin (S n)
FS :: Fin n -> Fin (S n)
type family ToNat (n :: Nat) (x :: Fin n) :: Nat where
ToNat (S n) FZ = Z
ToNat (S n) (FS x) = S (ToNat n x)
type ToNatAgain n x = ToNat n x -- similar error
ToNatAgain
应该有种类forall (n :: Nat) -> Fin n -> Nat
,但是变量x
的类型取决于变量n
的类型。 GHC 希望对其进行显式注释,因此它告诉我告诉它哪些变量依赖于哪些其他变量,并且它为我提供了它推断出的变量类型以帮助实现这一点。
type ToNatAgain (n :: Nat) (x :: Fin n) = ToNat n x
在你的例子中,依赖关系在 return 类型和参数类型之间。根本原因是相同的,但错误消息显然不是根据您的情况设计的,并且不适合。您应该提交错误报告。
顺便说一句,您真的需要单独的 Unwrap
和 GetType
吗?为什么不让 GetType
依赖?
type family GetType (pt :: Type) :: GetKind pt where
GetType (PolyType k t) = t