为什么在 Haskell 中声明参数化数据类型?

Why parameterised data type declaration in Haskell?

我看了一个 you-tube 视频,了解到有人使用参数化数据类型声明了一个新数据类型:

data Quad a = Quad a a a a
instance  (Show a) => Show (Quad a) where
show (Quad a b c d) = (show a) ++ " " ++  -- code continues for printing

我的疑问是为什么我们需要第一行代码。我做了这样的事情,它仍然有效。 我的代码:

data Q = Q Integer Integer Integer Integer 
instance  Show Q where
show (Q a b c d) = (show a)++" " ++ --code continues for printing

第一行 data Quad a = Quad a a a a 有什么用,而我们可以通过上面显示的方法来完成?请帮忙。提前致谢!

我不知道您对 Java 这样的命令式编程语言有多熟悉,但我假设您对 泛型 很熟悉。现在,您对 Q 的定义或多或少相当于 Java 中的某些内容,例如:

public class Q {

    private Integer field1;
    private Integer field2;
    private Integer field3;
    private Integer field4;

    public Q (Integer field1, Integer field2, Integer field3, Integer field4) {
        this.field1 = field1;
        this.field2 = field2;
        this.field3 = field3;
        this.field4 = field4;
    }

}

(是的,我知道 Java 中的 Integer 不等同于 Haskell 中的 Integer,但这不是问题)。

现在这限制了我们使用 ints。如果我们想要 quaterniondoubles 或 Cars,可能会出现问题。所以这不会很有效。

Quad 的原始定义在 Java 中是这样的:

public class 四边形<b><A></b> {

    私有 <b>A</b> 字段 1;
    私有 <b>A</b> 字段 2;
    私有 <b>A</b> 字段 3;
    私有 <b>A</b> 字段 4;

    public 四边形 (<b>A</b> field1, <b>A</b> field2, <b>A</b> field3, <b>A</b> 字段 4) {
        this.field1 = field1;
        this.field2 = field2;
        this.field3 = field3;
        this.field4 = field4;
    }

}

因此您可以使用 Quad<Integer>,它或多或少等同于上述 Q 的定义。但是我可以轻松地使用 Quad<Double>Quad<Car> 来构造双打、汽车、马……

的四元数

现在您可能认为马的四元数没有任何意义。四元数通常确实是在数字上指定的。但是有几种数据结构可以表示数字:Integers 可以——顾名思义——只能表示整数值。也许你也想允许 Doubles。此外 Integer 可以表示 所有 整数值(直到内存耗尽)。虽然这当然是一个不错的功能,但它需要付出代价:性能。在 Integer 上进行计算通常需要更多时间(即使它们具有 相同的 值)。因此,如果您想提高性能,您可以寻找 Quad Int16 例如。

通过使用类型参数,您可以获得一种灵活性:您不必定义一个看起来与另一个数据类型几乎相同的数据类型。

此外,您可以定义 - 如 Youtube 课程所示 - 对 a 施加约束的类型实例。因此,对于所有 a 可以被 show 编辑的 Quad a,您可以显示 Quad a。您还可以对函数施加约束。比如说你想提供一种方法来计算四边形的 "elements" 的总和。您可以定义:

sumquad :: <b>Num a =></b> Quad a -> a
sumquad (Q x y z t) = x + y + z + t

现在您已经为 all Quad a 类型定义了一个 sumquad 函数,其中 a 是 [=35= 的一个实例] typeclass (因此支持加法)。如果我们使用 QQ 应该有一个 sumquadQQDouble 应该有一个 sumquadQDouble(假设的 data QDouble = QDouble Double Double Double Double),等等.所以这需要大量的工作并且会导致代码不够优雅

Quad a a a a 允许您创建包含任何类型的四边形,而 Q Integer Integer Integer Integer 只允许整数。

所以这取决于你的四核能存储什么。如果你只存储整数,也许它应该被称为 IntegerQuad。一个原因可能是你想实现一个像

这样的函数
--collapse :: Q -> Integer
collapse Q(a,b,c,d) = a+b+c+d

除非指定了 (+),否则无法执行此操作。

在 Haskell 中,我认为您应该尽可能抽象,因为这会给您最大的灵活性,并且最有可能重用其他功能。