:~: 和 :~~: 等式有什么区别?
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
构造函数的实际模式匹配范围内之外,它不会说明种类是否相等,因此您可能不得不想出另一种方法来添加有关如果这就是你想要的,那么种类是平等的。
在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
构造函数的实际模式匹配范围内之外,它不会说明种类是否相等,因此您可能不得不想出另一种方法来添加有关如果这就是你想要的,那么种类是平等的。