在python中,我可以使用+
和-
添加(联合)和减去(差异)集。我如何在Haskell中设置它? (-) = Data.Set.difference
会有效吗?我试过了,但后来我认为常规减法数字搞砸了。
答案 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
module将Monoid
实现为union,因此您可以使用mappend
函数或(<>)
运算符来统一使用两个集合(或者附加两个列表)或许多其他事情。)
我担心Set.difference
运算符不是明显的流行类。
答案 2 :(得分:2)
要为类型定义Num实例,它将如下所示:
instance Num (Set a) where
(+) = -- definition
(-) = -- definition
-- etc
如果你只是在顶层定义:
(-) = -- definition
然后,您只是隐藏来自Num的(-)
。
作为bheklilr says,Set不是Num的有效实例,因为它不能满足环法。 Haskell不会禁止你定义实例,但这是一个糟糕的主意。人们通过使用他们的法律来处理类型类,因此违反它们会导致程序错误。