【问题标题】:What is the differences between class and instance declarations?类和实例声明之间有什么区别?
【发布时间】:2012-09-21 11:17:46
【问题描述】:

我目前正在阅读this,但老实说,我很难看到什么

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

达到,这

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

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

【问题讨论】:

  • 一个是类型类,另一个是类型实例。前者描述了该类型类的类型可以做什么(接口),后者描述了它是如何完成的(实现)。 (免责声明:我真的不知道 Haskell。这是从语法和我读到的很少内容的一个疯狂猜测。)
  • @Xeo 你是对的。可以解释为 Haskell 的类型类与 java 的接口相匹配。 Haskell 的实例匹配 Java 的接口实现。
  • @Philipp Haskell 类型的类与 oop 无关。

标签: haskell instance typeclass


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 那么第一个好像是OO接口?两者有关系吗?是否可以使用没有实例的类,反之亦然?
    • 有一些相似之处,但它们根本不一样。您可以编写使用类而不定义任何实例的函数。但是如果没有具有该类实例的类型,则不能调用这些函数。我帖子中的示例不需要任何实例存在,但调用函数需要。无论如何,我认为从 OOP 的角度来考虑它并不好。
    • 所以 Eq a 说“我(或 Prelude)已经为类型 a 定义了相等函数?所以这意味着编译器可以静态地允许它编译(强调 - 你可能没有定义他们并收到运行时错误??)
    • 不,Eq a 的意思是“调用此函数的任何人都可以使用任何类型 a,只要该类型 a 实现 Eq 类型类。”任何尝试使用未实现该类型类的类型调用函数都将导致 compile-time 错误。
    • @mezamorphic:它们并不真正相关,但就类型类的根本错误类比而言,“像 OO 接口”是我所知道的最不错误的。类型类通常比接口更强大,但在许多方面它们的用途相似。
    【解决方案3】:

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

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

    【讨论】:

    • 你同意 Xeo 的评论吗?如果是这样,我明白了吗?
    【解决方案4】:

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

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

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

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

    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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-09
      • 2016-11-12
      • 1970-01-01
      • 1970-01-01
      • 2019-07-25
      • 1970-01-01
      • 2012-07-15
      • 2015-11-21
      相关资源
      最近更新 更多