定义幻影类型 - 无法编译示例

Defining Phantom Types - can't compile examples

我想了解更多关于 Phantom 类型的信息。我正在尝试通读 Ralf Hinze 的 Fun with Phantom Types。他使用的关键字 with 我以前没见过,我无法编译。当我尝试此操作时,我在 = 上收到解析错误。

data Type t = RInt                    with t = Int
            | RChar                   with t = Char
            | RList (Type a)          with t = [a ]
            | RPair (Type a) (Type b) with t = (a, b)

在论文的前面,他说 "with" 语句不是绝对必要的,你可以设置 a = t 代替,但我不知道如何定义这种数据类型没有他们。以下错误:Not in scope: type variable 'a'

data Type t = RInt
            | RChar
            | RList (Type a)
            | RPair (Type a) (Type b)

我错过了什么?

虽然丑陋,但以下内容可以工作,并且在精神上可能被认为更接近于该表示法。这实质上是将 GADT 脱糖为类型等式(它们似乎没有自己的扩展名,因此您需要 either GADTsTypeFamilies 才能使用它们)和存在性.

{-# LANGUAGE ExistentialQuantification, TypeFamilies #-}

data Type t = t ~ Int => RInt
            | t ~ Char => RChar
            | forall a. t ~ [a] => RList (Type a)
            | forall a b. t ~ (a, b) => RPair (Type a) (Type b)

我的猜测是论文中建议的定义 sans-with

data Type t = RInt
            | RChar
            | RList (Type t)
            | RPair (Type t) (Type t)

以上,从未使用过参数t。确实是幻影

这意味着,例如

RInt :: Type a

对于任意类型a。相比之下,如果遵循 with 约束,则除了 t ~ Int.

之外,任何 t 都不可能具有 RInt :: Type t

GHC 中不存在 with 语法,但 GADT 的作用基本相同。

{-# LANGUAGE GADTs #-}
data Type t where
   RInt  :: t ~ Int   => Type t
   RChar :: t ~ Char  => Type t
   RList :: t ~ [a]   => Type a -> Type t
   RPair :: t ~ (a,b) => Type a -> Type b -> Type t

注意在每个构造函数中 with 是如何被等式约束替换的。基本上是一样的东西,写法不一样。

更紧凑,我们可以将上面的重写成

data Type t where
   RInt  :: Type Int
   RChar :: Type Char
   RList :: Type a -> Type [a]
   RPair :: Type a -> Type b -> Type (a,b)

最终类型中的约束 "inlined"。