Haskell中`==`的类型应该是'Eq a b => a - > b - > Bool`

时间:2014-12-13 03:37:55

标签: haskell types equality typeclass

(==)的类型是Eq a => a -> a -> Bool,但我可以想象一个更通用的版本Eq a b => a -> b -> Bool,当类型不匹配时它是假的,并且只是通常的平等类型匹配。为什么不是这样?

4 个答案:

答案 0 :(得分:14)

我们可以根据EqTypeable from Data.Typeable来定义。我们可以比较Typeable的事物类型来检查它们是否是同一类型。

(?==) :: (Eq b, Typeable a, Typeable b) => a -> b -> Bool
x ?== y = cast x == Just y

cast检查一个Typeable类型的值实际上是否与另一个类型相同。如果输入属于同一类型,则返回Just;如果类型不同,则返回Nothing

以下是一些展示所需行为的例子。

> 7 ?== 7
True

> 7 ?== "hello"
False

> 7 ?== 5
False

> (7 :: Int) ?== (7 :: Integer)
False

答案 1 :(得分:7)

(==) :: Eq a b => a -> b -> Bool不会像你想象的那样有用。

要确定2参数Eq的实例,您需要知道两种类型(足以匹配实例)。此==的所有来电者都需要具体了解ab,或者在其界面中传递约束;然后他们自己的调用者需要知道ab是什么,或者传递约束......在某些时候必须选择Eq实例,而不是通过约束,包括在编译时了解ab

那时,你为什么要打扰?如果您知道ab相同,那么单个参数Eq足以比较它们。如果您知道它们不同,那么您知道答案是False,并且您不需要任何实例来告诉您。如果您没有知道它们是相同还是不同,那么根据定义,您不了解选择Eq实例,因此您可以&#39 ; t根本调用==(或Eq - 约束函数)!

因此,这不会帮助您从不同的来源获得ab未知类型(实现相等),然后进行比较。他们必须与一个Eq a b实例结合在一起,这实际上是一个编译时证明它们是否属于同一类型,

@ Cirdec的答案中的Typeable版本非常不同,而且更有用。每个类型 independentlly 支持Typeable,其中一个支持单参数Eq;你可以从两个不同的来源获得这两个值,你不知道它们是否相同,但你知道你可以检查每个值的类型; a来源必须知道a以便选择Typeable个实例,b来源必须知道b以便选择TypeableEq实例,但两个源都不必知道关于其他类型的任何内容,并且没有代码必须同时知道这两种类型,以确定它们是否相同(在编译时间)。 2参数Eq强制同时知道这两种类型,这会使它几乎毫无价值。

答案 2 :(得分:3)

我认为对你的问题的哲学答案是Haskell本质上类似于数学,当我们把数学对象放在数学对象上并定义数学对象的相等性时,我们通常认为这两个对象属于同一类型。例如。看看如何定义集合等式。

现在,这组自然数是否等于自然数6?或者让我们变得狂野 - 椅子是否等于整数-7?虽然我很想让我的直觉接管和尖叫,但当然不是!#34;我真的不能这么说,因为问题本身是无效的,它是' ; s都是非常不确定的。集合和自然之间的平等是不确定的。主席和整数之间的平等是不确定的。

这是否意味着你无法定义它?不,继续。
但它并不是一种非常流行的方法,因此基础库的选择是非常容易理解的。


作为对您评论的回复,这是正确的。碰巧,集合是如此原始,以至于我们可以用它们代表任何东西。这只是一个例子,如果我们选择其他东西,我也不知道你是否可以同样争论,但不管怎样,让我们​​骑它。

对于集合A等于集合B,我们需要:

  1. A中的每个元素都存在于B
  2. B中的每个元素都存在于A
  3. 非常简单地说,集合{1,2,3}是否等于7?我不知道,因为说7中存在的元素未定义,问题无效。

    但是,让我们采取你的方法,并按照你的说法做:拿7,穿上漂亮的衣服举起它并称之为C组,让我们甚至假设C等于D组表明你是对的。您可以要求7和另一组之间的相等,最终。但我只是想让你注意到在我们做到这一点之前,我们必须如何努力使它成为一个集合。如果可能的话,这正是Haskell想要你做的。使用数学集合,它几乎总是可行的。

    因此,无论是在Haskell和数学中,我们(仍然)都无法真正地问:

    (a :: Set) == (7 :: Natural)
    

    然而,在Haskell和数学中我们都可以先提升它,这样我们就可以用不同的方式来看待它,然后我们可以问:

    (liftN :: Natural -> Set) (7 :: Natural) == (a :: Set)
    

    当然,RHS是集合C.

    这个答案的要点是,Haskell只是通过以它的方式定义相等而在常见的数学术语中是惯用的。

答案 3 :(得分:2)

Haskell的观点是,只检查相同类型的两个值的相等性是有意义的,即检查两个不同类型值的相等是没有意义的,很可能意味着你在做错了程序。这就是(==)的类型就是它的原因。

一般来说,这就是在强大的类型系统(如Haskell)中工作的意思。它旨在帮助编写更好,更有意义的程序。