作为类型驱动编程的初学者,我对使用 ==运算符感到好奇。示例表明,证明某种类型的两个值之间的相等性是不够的,并且为特定数据类型引入了特殊的相等性检查类型。在这种情况下, == 在哪里有用?
答案 0 :(得分:3)
(==)
(作为Eq
接口的单一组成函数)是类型T
到Bool
的函数,适用于等式推理。鉴于x = y
(其中x : T
和y : T
)AKA"内涵平等"本身就是一种类型,因此也是一种命题。您可以并且经常希望在表达特定类型的相等性的两种不同方式之间来回反弹。
x == y = True
也是一个命题,通常是推理(==)
和推理=
之间的中间步骤。
两种类型的平等之间的确切关系相当复杂,您可以阅读Twilio Two-Factor Authentication以了解我自己尝试理解它的某些方面。 (需要注意的一点是,即使一个归纳定义的类型具有可确定的内涵相等性,你仍然需要通过一些箍来证明这一点,并且需要更多的箍来定义Eq
的相应实现。)
一个特别方便的代码片段是:
-- for rel x y, provide both the computed value, and the proposition that it is equal to the value (as a dependent pair)
has_value_dpair : (rel : t -> t -> Bool) -> (x : t) -> (y : t) -> (value: Bool ** rel x y = value)
has_value_dpair rel x y = (rel x y ** Refl)
如果您从with
返回了值,并且想要推断命题rel x y
或rel x y = True
(和{{rel x y = False
,则可以将其与rel
构造一起使用1}}是一些可能代表x
和y
之间平等概念的函数。
(在这个答案中,我假设(==)
对应=
的情况,但您可以完全自由地定义(==)
函数,该函数与{{1}不对应例如,在定义 Setoid 时。这是使用=
代替(==)
的另一个原因。)
答案 1 :(得分:2)
你仍然需要良好的旧平等,因为有时你无法证明事情。有时你甚至不需要证明。考虑下一个例子:
countEquals : Eq a => a -> List a -> Nat
countEquals x = length . filter (== x)
您可能只想计算相等元素的数量,以向用户显示一些统计信息。另一个例子:测试。是的,即使使用强类型系统和依赖类型,您也可能希望执行良好的旧单元测试。所以你想检查期望,这对(==)
运算符来说非常方便。
我不会写出您可能需要(==)
的完整案例列表。平等操作员不足以证明,但你并不总是需要证明。