3

我目前正在阅读这篇文章,但老实说,我很难看到什么

class Eq a where 
  (==)                  :: a -> a -> Bool

达到,其中

instance Eq Integer where 
  x == y                =  x `integerEq` y

没有达到。我知道第二个代码定义了对两个 Integer 类型执行相等的结果应该是什么。那么第一个的目的是什么?

4

4 回答 4

8

声明说“class我现在要定义一堆函数,它们将适用于几种不同的类型”。声明说“这instance就是这些函数对这种类型的工作方式”。

在您的具体示例中,class Eq表示“Eq表示具有名为==”的函数的任何类型,而instance Eq Integer表示“这就是“==的工作方式Integer”。

于 2012-09-21T14:08:12.243 回答
4

第一个定义必须为类型提供哪些操作才能进行相等比较。然后,您可以使用它来编写对任何可比较相等的类型进行操作的函数,而不仅仅是整数。

allSame :: Eq a => [a] -> Bool
allSame [] = []
allSame (x:xs) = foldr True (==x) xs

此函数适用于整数,因为Eq Integer存在的实例。它也适用于字符串 ( [Char]),因为Eq Char存在的实例和具有实例的类型列表的实例Eq也存在 ( instance Eq a => Eq [a])。

于 2012-09-21T11:25:00.640 回答
2

不同类型有一个类和多个实例。这就是类指定所需签名(接口;类也可以指定默认实现,但这不是重点)和实例主体(实现)的原因。然后,您使用类名作为约束,这意味着“任何a实现Eq操作的类型,即在其中有一个实例Eq”。

阅读Learn you a HaskellReal World Haskell,它们比 haskell.org 教程更好。

于 2012-09-21T11:22:28.943 回答
0

假设您想实现一个通用算法或数据结构,“通用”意味着多态:它应该适用于任何数据类型。例如,假设您要编写一个函数来确定三个输入值是否相等。

以特定的(单态)情况为例,您可以对整数执行此操作:

eq3 :: Int -> Int -> Int -> Bool
eq3 x y z = x == y && y == z

当然,我们希望上述定义也适用于其他类型,但如果我们只是告诉编译器该函数应该适用于任何类型:

eq3 :: a -> a -> a -> Bool
eq3 x y z = x == y && y == z

...编译器抱怨该==函数不适用于我们的泛型a

<interactive>:12:49:
    No instance for (Eq a)
      arising from a use of `=='
    In the first argument of `(&&)', namely `x == y'
    In the expression: x == y && y == z
    In an equation for `eq3': eq3 x y z = x == y && y == z

我们必须告诉编译器我们的类型a是类型类的一个实例Eq你已经注意到它是==函数被声明的地方。看看这里的区别:

eq3 :: Eq a => a -> a -> a -> Bool
eq3 x y z = x == y && y == z

a现在我们有了一个可以对属于Eq类型类的任何类型进行统一操作的函数。

于 2012-09-23T20:17:26.570 回答