:~: 和 :~~: 等式有什么区别?

What is the difference between :~: and :~~: equalities?

Data.Type.Equality中定义了两个类型级别的等式::~::~~:。据说它们分别代表同质和异质平等,但我真的看不出它们之间有什么区别。这是什么?

老实说,由于类型系统中值、类型和种类之间的严格界限,我看不到在 Haskell 类型中实现真正的异构相等的方法。

区别在于它们的种类:

type (:~:)  :: k  -> k  -> Type
type (:~~:) :: k1 -> k2 -> Type

前者只接受两个类型相同的参数,而后者则没有这样的限制。

类型Bool :~: Maybe是ill-kinded(会触发类型错误),而Bool :~~: Maybe是well-kinded。后者是空的,但至少我们可以写它而不会触发错误。

非常简单。

ghci> :k (:~:)
(:~:) :: k -> k -> *

ghci> :k (:~~:)
(:~~:) :: k1 -> k2 -> *

请注意,Data.Type.Equality 指出 :~~: 是“种类 异构命题相等性”(强调我的),因此您需要查看种类。

基本上 :~: 类似于 term-level ==,因为使用它需要您检查相等性的两种类型是同类成员。不同种类的类型(比如不同类型的术语)绝对不相等,但是 :~:(比如 ==)你甚至会因为考虑这个问题而被拉起来。

但是 :~~: 即使您尚未确定这两种类型具有相同的种类,也可以使用。当类型(以及种类)不相等时,您将无法构造 Refl :: a :~~: b,但是 GHC 可以考虑(空)类型 a :~~: b 的存在,当它们不相等时与 a :~: b.

不同

所以你可以在一些你不能使用:~:的情况下使用:~~:。但有时这种灵活性实际上是一个问题。如果您希望两侧具有相同的类型,请将它们与 :~: 添加 编译器的信息(可能需要它来解析类型 class 实例或类型家庭等)。如果您使用 :~~: ,除了在 Refl 构造函数的实际模式匹配范围内之外,它不会说明种类是否相等,因此您可能不得不想出另一种方法来添加有关如果这就是你想要的,那么种类是平等的。