定义幻影类型 - 无法编译示例
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 GADTs
或 TypeFamilies
才能使用它们)和存在性.
{-# 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"。
我想了解更多关于 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 GADTs
或 TypeFamilies
才能使用它们)和存在性.
{-# 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
.
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"。