是否有某种方式(任何方式)在类型类中实现约束?
作为我所谈论的一个例子,假设我想将一个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是唯一可能具有两个元素的组)。有没有办法使这项工作?
答案 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