6

constructive-algebra允许您定义代数模块的实例(如矢量空间,但使用需要字段的

这是我定义模块的尝试:

{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
module A where
import Algebra.Structures.Module
import Algebra.Structures.CommutativeRing
import Algebra.Structures.Group

newtype A = A [(Integer,String)]

instance Group A where
    (A a) <+> (A b) = A $ a ++ b
    zero = A []
    neg (A a) = A $ [((-k),c) | (k,c) <-  a]


instance Module Integer A where
    r *> (A as) = A [(r <*> k,c) | (k,c) <- as]

它失败了:

A.hs:15:10:
    Overlapping instances for Group A
      arising from the superclasses of an instance declaration
    Matching instances:
      instance Ring a => Group a -- Defined in Algebra.Structures.Group
      instance Group A -- Defined at A.hs:9:10-16
    In the instance declaration for `Module Integer A'

A.hs:15:10:
    No instance for (Ring A)
      arising from the superclasses of an instance declaration
    Possible fix: add an instance declaration for (Ring A)
    In the instance declaration for `Module Integer A'
Failed, modules loaded: none.

如果我将Group实例注释掉,那么:

A.hs:16:10:
    No instance for (Ring A)
      arising from the superclasses of an instance declaration
    Possible fix: add an instance declaration for (Ring A)
    In the instance declaration for `Module Integer A'
Failed, modules loaded: none.

我将其读为需要一个实例,该实例Ring A没有Module Integer A意义,并且在类定义中也不需要:

class (CommutativeRing r, AbelianGroup m) => Module r m where
  -- | Scalar multiplication.
  (*>) :: r -> m -> m

你能解释一下吗?

4

2 回答 2

5

该软件包包含一个

instance Ring a => Group a where ...

实例头a匹配每个类型表达式,因此具有任何其他类型表达式的任何实例都将重叠。只有在某个地方实际使用了这样的实例时,这种重叠才会导致错误。在您的模块中,您使用实例

instance Module Integer A where
    r *> (A as) = A [(r <*> k,c) | (k,c) <- as]

该类对参数ModuleAbelianGroup限制¹。m这意味着一个Group约束。所以对于这个实例,必须查找的Group实例。A编译器找到两个匹配的实例。

这是第一个报告的错误。

下一个是因为编译器试图AbelianGroupA. 编译器此时知道的唯一实例是

instance (Group a, Ring a) => AbelianGroup a

所以它试图找到instance Ring A where ...,但当然没有。

而不是注释掉instance Group A where ...,您应该添加一个

instance AbelianGroup a

(即使是谎言,我们现在只想让它编译)并添加OverlappingInstances
{-# LANGUAGE #-}pragma 中。

使用OverlappingInstances,选择最具体的匹配实例,所以它在这里做你想要的。

¹顺便说一句,除非订单在列表中无关紧要,否则您A不是一个实例,AbelianGroup而且理所当然地不可能。[(Integer,String)]

于 2012-05-10T16:06:21.247 回答
2

这种类型的检查没有令人讨厌的语言扩展。

{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
module A where
import Algebra.Structures.Module
import Algebra.Structures.CommutativeRing
import Algebra.Structures.Group

newtype A = A [(Integer,String)]

instance Ring A where 
  A xs <+> A ys = A (xs ++ ys)
  neg (A a) = A $ [((-k),c) | (k,c) <-  a]
  A x <*> A y = A [b | a <- x, b <- y ]
  one = A []
  zero = A []

instance Module Integer A where
     r *> (A as) = A [(r <*> k,c) | (k,c) <- as] 

<+> <*>在andneg中独立定义Ringand有点令人困惑 Group;它们是完全独立的符号,但随后它们在使 all 的一般实例中组合在一起Rings Groups,因此如果Ring已定义,则Group不能定义,因为它已经说过了。我不确定这是由类型类系统的工作方式强加给作者的。 Module需要Ring或者更确切地说CommutativeRingCommutativeRing基本上只是重命名Ring;没有进一步的定义。它应该让你接受 Haskell 中不可检查的交换性断言。因此,可以说,您应该在模块之外“证明CommutativeRing法律”,然后再进行Module实例。但是请注意,这些定律在快速检查命题中表达,因此您应该运行快速检查propMulCommpropCommutativeRing专门针对这种类型。

不知道如何处理 1 和 0,但是您可以通过使用合适的结构来解决关于顺序的问题,也许:

 import qualified Data.Set as S

 newtype B = B {getBs :: S.Set (Integer,String) }

但是,我想,有了新类型,你也可以重新定义EqA 以理解它。事实上,您必须运行快速检查命题。


编辑:这是一个版本,其中包含 QuickCheck http://hpaste.org/68351所需的附加材料以及不同 Eq 实例的“失败”和“确定”快速检查语句。这个包对我来说似乎很合理;如果您不想要 Ring 和 CommutativeRing 业务,我认为您应该重新定义 Module,因为他说他“只考虑交换情况,可以改为实现左右模块。” 否则,您将无法使用快速检查,这显然是该软件包的主要要点,现在我看到了发生了什么,并且他使这变得非常容易做到。因为 A 正是他试图通过普遍使用快速检查来排除的那种事情,在这种情况下肯定很难欺骗。

于 2012-05-10T17:01:04.217 回答