重载+, - 用于haskell中的集合

时间:2015-12-30 20:43:01

标签: haskell operator-overloading

在python中,我可以使用+-添加(联合)和减去(差异)集。我如何在Haskell中设置它? (-) = Data.Set.difference会有效吗?我试过了,但后来我认为常规减法数字搞砸了。

3 个答案:

答案 0 :(得分:6)

Haskell对数值运算符的重载比Python更多限制,为了定义它们,必须遵循规则和法则。例如,您还需要定义*abs。相反,使用已经在Data.Set中定义的运算符,即\\来设置差异,并且没有一个已经为union定义,但是您可以轻松地创建自己的别名,或者可以将其用作

set1 `union` set2

我建议坚持使用已经定义的函数和运算符,它会使你的代码对其他任何看过它的人都更具可读性。随意引入新的运算符,这些运算符不仅仅是对现有函数进行别名,尽管良好实践仍然谨慎地这样做。

答案 1 :(得分:3)

你建议做的是,有点滑稽,非常不可思议。 Haskellers通常采取以下态度:

  • 同名或符号不应重载,以表示两种不同的东西。

这意味着所有可重写的名称或符号(即类操作)必须具有一致的核心,这意味着它们的所有重载实例都必须遵守。

在Haskell中,(+)(-)操作由the Num class定义。文档并不是明确的,但是要实现一个类,你必须实现它的所有方法,包括fromInteger :: Num a => Integer -> a(将任何Integer转换为类的实例的操作)和abs :: Num a => a -> a(取一个数字的绝对值)。

如果没有深刻地滥用其含义,则无法为集合实现Num类。所以不要这样做。

请注意,还有其他类可能更适合您尝试执行的操作。例如,the Monoid class提供适用于集合的通用操作。实际上,the Data.Set moduleMonoid实现为union,因此您可以使用mappend函数或(<>)运算符来统一使用两个集合(或者附加两个列表)或许多其他事情。)

我担心Set.difference运算符不是明显的流行类。

答案 2 :(得分:2)

要为类型定义Num实例,它将如下所示:

instance Num (Set a) where
  (+) = -- definition
  (-) = -- definition
  -- etc

如果你只是在顶层定义:

(-) = -- definition

然后,您只是隐藏来自Num的(-)

作为bheklilr says,Set不是Num的有效实例,因为它不能满足环法。 Haskell不会禁止你定义实例,但这是一个糟糕的主意。人们通过使用他们的法律来处理类型类,因此违反它们会导致程序错误。