我是否应该为适合接口的类型实例化Num类型类?

  • 本文关键字:类型 实例化 Num 接口 是否 haskell
  • 更新时间 :
  • 英文 :


在我看来,Num类型类由一个相当任意的函数集合组成。有许多类型自然具有+*操作,但由于abssignumfromInteger的存在,作为Num的实例存在问题。我找不到任何关于这门课背后的设计哲学的讨论,所以我不清楚这里是否有一个合理的理由,或者它是否是一个不幸的历史怪现象。

我来举例说明我的问题。假设我正在实现一个Matrix类,其组件是Double。我显然可以实现+, *, -negate。也许fromInteger x可以给一个1x1 Matrix与组件DoublefromInteger x。如何处理abssignum不太明显,但我可以提出一些满足规则的东西(来自类的文档):
abs x * signum x == x

这个想法的反对意见是,我的Num实例没有满足人们期望Num的一些隐含规则。我的*是一个部分函数(假设Matrix的大小是一个运行时参数),对于DoubleInt这样的常见实例来说,情况并非如此。而且不用通勤。无论我为abssignum想出什么,都不会满足每个人的期望。

对这个反对意见的反对意见是,我的Matrix乘法无论如何都将是一个部分函数(并且在Haskell社区中似乎被接受的这种类型中),那么为什么它特别重要,特别是*是部分函数?如果我的abssignum满足文档中的规则,那么我就完成了我的交易。任何依赖Num实例的人都是错误的。

Matrix这样的类型应该是Num的实例吗?

不要为非环创建Num实例。这太令人困惑了。

当然,你可以经常定义实例来做一些有用的事情,但是如果不是很明显做什么,那么最好只是定义一个具有描述性名称的普通函数,或者一些具有更好定义语义的弱类实例。如果有人想使用短操作符或多态Num函数,他们仍然可以在自己的模块中本地定义它(最好使用简单的newtype包装器)。 特别是,一般(动态大小)矩阵的Num实例是有问题的,因为当维度不匹配时不明显会发生什么。你想概括一下什么行为?
我认为一个很好的例子是固定二次大小的矩阵(即给定向量空间上的线性自同态)。在这种情况下,乘法显然是组合,数字文字将被视为常数对角矩阵,因此1实际上是乘法单位。就像你在数学背景下写的。

但这与您任意选择数字字面值的大小为1×1的想法是不兼容的!人们期望2 * m工作,但它崩溃了。与其产生意想不到的结果,不如崩溃;不幸的是,我们很容易想出一些聪明的方法来定义乘法。例如,我们可以对角块复制较小的矩阵,直到它足够大,也许只在1& *;1的情况下这样做……好吧,Matlab做这种特别的东西,但请!我们不要把这种可怕的语言当作什么是好主意的榜样。

如果你有一个明显是加性群的东西,实际上是向量空间,那么让它成为VectorSpace !如果你也有一个乘法,但它是偏乘法,那么最好只把它定义为一个普通函数。

如果您愿意,您可以为精细交错的数字前奏类定义实例。就我个人而言(尽管我喜欢这个项目的想法),我还不能在任何地方使用它,因为要理解层次结构是相当费力的。


& 还是?麻烦已经开始了,我认为hmatrix实际上在矩阵上实现了*作为元素明智的乘法。这比Matlab还可怕!

相关内容

最新更新