我怎样才能对我的 GADT 脱糖?

How can I desugar my GADTs?

我正在阅读 Coercions and Roles for Dummies,作者随手提到 GADT 只是语法糖。

GADTs are syntactic sugar on top of (~) so expect GADTs to have nominal role type parameters.

现在作者没有进一步讨论这个,因为这不是博客的重点post。但是我很好奇。我怎样才能让我的 GADT 脱糖?

例如,这里是一个使用 GADT 的简单异构列表。

{-# Language GADTs, DataKinds, TypeOperators #-}

data HList a where
  Empty :: HList '[]
  Cons  :: a -> HList b -> HList (a ': b)

脱糖后的版本会是什么样子?

你可以将你的 GADT 脱糖到这个:

data HList t where
  Empty :: t ~ '[]      => HList t
  Cons  :: t ~ (a ': b) => a -> HList b -> HList t

这不再是 "real" GADT,因为每个构造函数 returns 都是通用类型 HList t,就像它发生在普通的旧代数数据类型中一样。

诀窍是类型变量t在结果类型HList t中看起来不受约束,但实际上受到类型相等约束t ~ ...的限制,因此获得相同的语义作为原始类型。

如果你想完全删除GADT语法,你可以按照下面的方式进行。您仍然需要打开一些扩展程序才能使用 ~ 约束。

{-# LANGUAGE DataKinds, TypeOperators, TypeFamilies, ExistentialQuantification #-}
data HList2 t
   = t ~ '[] => Empty2
   | forall a b .  t ~ (a ': b) => Cons2 a (HList2 b)

你说的那篇论文大概是在指出,由于t涉及到等式约束,所以它的作用是名义上的。