定义类型同义词(GHC)的类型同义词时出现奇怪的错误

时间:2018-09-22 15:34:01

标签: haskell types ghc type-synonyms

背景

我已经在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

此代码的目的是允许我将任意类型的类型包装为单一类型(即PolyType)的类型(即Type),然后逆转该过程(即拆开)。

问题

我想为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,但这感觉很棘手,我希望有更好的方法。

不幸的是,我对GHC的内部运作还没有足够的经验,甚至无法确切地了解问题所在,更不用说解决问题了。

我相信我对我正在使用的扩展名(例如TypeInTypePolyKinds)的工作方式有很好的了解,但显然尚不足以理解此错误。此外,我还没有找到解决类似问题的资源。部分原因是因为我不知道如何简洁地描述它,这也使得很难为这个问题找到一个好标题。

1 个答案:

答案 0 :(得分:2)

该错误非常晦涩,但我认为它试图说明的是GHC已经注意到UnwrapSynonym的类型是依赖的,forall (pt :: Type) -> GetKind pt,并且它希望您显式地注释依赖关系:

type UnwrapSynonym pt = (Unwrap pt :: GetKind pt)

之所以要告诉它“哪些变量取决于其他变量”是因为该错误也会在例如这种情况:

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

在您的情况下,依赖关系介于返回类型和参数类型之间。根本原因是相同的,但是错误消息显然不是针对您的情况设计的,因此不合适。您应该提交错误报告。

顺便说一句,您真的需要单独的UnwrapGetType吗?为什么不让GetType依赖?

type family GetType (pt :: Type) :: GetKind pt where
  GetType (PolyType k t) = t