类和实例声明之间有什么区别?

时间:2012-09-21 11:17:47

标签: haskell instance typeclass

我目前正在阅读this,但如果我说实话,我很难看到

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

实现,

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

没有实现。我理解第二个代码定义了在两个Integer类型上执行相等的结果应该是什么。第一个的目的是什么呢??

4 个答案:

答案 0 :(得分: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])。< / p>

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

class声明说“我现在将定义一系列功能,这些功能将适用于多种不同的类型”。 instance声明说“这就是类型的这些函数的用法”。

在您的具体示例中,class Eq表示“Eq表示任何具有名为==的函数的类型”,而instance Eq Integer表示“这就是== 1}}适用于Integer“。

答案 3 :(得分: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

我们必须告诉编译器我们的类型aEq类型类的实例,您已经注意到它是==函数的位置被宣布。看到这里的区别:

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

现在我们有一个函数可以在属于a类型类的任何类型Eq上统一运行。