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

时间:2017-05-10 09:50:22

标签: haskell types instance type-parameter

我浏览了一个you-tube视频并了解到该人使用参数化数据类型声明了一种新的数据类型:

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

第一行的使用是什么{{1}},而我们可以通过上面显示的方法来实现它?请帮忙。提前谢谢!

2 个答案:

答案 0 :(得分:6)

我不知道你对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,但这不是问题。)

现在这限制了我们使用int s。如果我们想要一个带有double s或Car s的四元数,可能会出现问题。所以这不会非常有效。

Quad的原始定义可能是Java中的内容:

public class Quad<A> {

    private A field1;
    private A field2;
    private A field3;
    private A field4;

    public Quad (A field1, A field2, A field3, A field4) {
        this.field1 = field1;
        this.field2 = field2;
        this.field3 = field3;
        this.field4 = field4;
    }

}

因此,您可以使用Quad<Integer> - 或多或少 - 与上述Q的定义相同。但我可以轻松地使用Quad<Double>Quad<Car>来构建双打,汽车,马匹的四元数......

现在你可能会认为马的四元数没有任何意义。通常确定四元数超过数字。但是有几种数据结构可以表示数字:Integer可以 - 顾名思义 - 只代表整数值。也许您也想允许Double。此外,Integer可以表示所有整数值(直到内存耗尽)。虽然这当然是一个很好的功能,但它带来了成本:性能。在Integer上进行计算通常需要更多时间(即使它们具有相同的值)。因此,如果您想提高性能,可以查找Quad Int16

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

此外,您可以定义 - 如Youtube课程所示 - 键入您在a上设置约束的实例。因此,对于Quad a可以a编辑的所有show,您可以显示Quad a。您还可以对函数设置约束。比如说你想提供一种方法来计算&#34;元素的总和&#34;四边形。你可以定义:

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

现在您已为所有 sumquad类型定义了Quad a函数,其中aNum类型类的实例(因此支持补充)。如果我们使用QsumquadQ QsumquadQDouble QDouble(假设data QDouble = QDouble Double Double Double Double)等应该是SELECT id, status, category, logourl, businessname, slug, address2, city, state, country, zipcode, latitude, longitude, isclaimed FROM (SELECT distance(33.8730134379712132, -117.5613892553118574,longitude , latitude) AS distance, id, status, category, logourl, businessname, slug, address2, city, state, country, zipcode, latitude, longitude, isclaimed, rank() over (partition by businessname, city, category order by id desc) AS rank FROM hmgravy_yelpbusiness ) as dt where rank = 1 AND slug != '' AND status = True AND isclaimed!='Y' AND (longitude <= 34.01794097420309 AND longitude >= 33.72808590173933 AND ABS(latitude) <= 117.75476524524271 AND ABS(latitude) >= 117.368013265381) AND distance <= 10 AND category = 'General Contractors' ORDER BY CASE WHEN LOWER(city) = 'corona' THEN 1 ELSE 2 END , distance ASC, city ASC, logourl DESC LIMIT 15 OFFSET 0 因此,它需要大量的工作,并且会导致代码不那么优雅。

答案 1 :(得分:3)

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中,我相信你应该尽可能抽象,因为这会给你最大的灵活性,最有可能重用其他功能。