有没有办法在Haskell的类型类中实现约束?

时间:2010-02-12 16:18:36

标签: haskell functional-programming class constraints typeclass

是否有某种方式(任何方式)在类型类中实现约束?

作为我所谈论的一个例子,假设我想将一个Group实现为一个类型类。因此,如果有三个函数,则类型将是一个组:

class Group a where
    product :: a -> a -> a  
    inverse :: a -> a 
    identity :: a

但那些不是任何功能,但它们必须通过一些约束相关联。例如:

product a identity = a 
product a (inverse a) = identity
inverse identity = identity

等...

有没有办法在类的定义中强制执行这种约束,以便任何实例都会自动继承它?例如,假设我想实现C2组,由以下人员定义:

 data C2 = E | C 

 instance Group C2 where
      identity = E 
      inverse C = C

这两个定义唯一地确定C2(上述约束定义了所有可能的操作 - 实际上,由于约束,C2是唯一可能具有两个元素的组)。有没有办法使这项工作?

3 个答案:

答案 0 :(得分:11)

  

有没有办法强制执行这种约束?

不。 很多的人一直在要求它,包括着名的Tony Hoare,但是现在还没有出现。

这个问题对于Haskell Prime小组来说是一个很好的讨论主题。如果有人提出了一个好的提案,可能会在那里找到。

P.S。这是一个重要的问题!

答案 1 :(得分:8)

在某些情况下,您可以使用QuickCheck指定属性。这不是完全强制执行,但它允许您提供所有实例应该通过的通用测试。例如,对于Eq,您可能会说:

prop_EqNeq x y = (x == y) == not (x != y)

当然,实例作者仍然需要调用此测试。

为monad法律做这件事会很有趣。

答案 2 :(得分:5)

类型类可以包含定义和声明。例如:

class Equality a where
    (?=), (!=) :: a -> a -> Bool

    a ?= b = not (a != b)
    a != b = not (a ?= b)

instance Eq a => Equality a where
    (?=) = (==)

test = (1 != 2)

您还可以在普通的Haskell中指定特殊约束(让我们将它们称为 law ),但不能保证编译器会使用它们。一个常见的例子是monadic laws