为多项式创建Eq实例

时间:2015-04-29 01:13:53

标签: haskell

在Haskell中表示多项式:

newtype Poly a = P [a]
x :: Num a => Poly a
x = P [1]

instance (Num a, Eq a) => Eq (Poly a) where

E.g。 P[1,2,3] = 3x^2 + 2x + 1

我想说两个多项式是相等的,如果它们具有相同的列表(例如P[1,2,3]等于P[1,2,3])。如果列表相同,则它们也是相同的,除了最后一个元素是0'(例如P[1,2,3]等于P[1,2,3,0,0])。

但是,我不知道如何执行此操作的语法。

2 个答案:

答案 0 :(得分:4)

实施Eq

只需延伸Jakes的答案,就可以得到一个完整的答案:

我喜欢删除前导零的想法,然后你很快就会结束:

newtype Poly a = P [a]

instance (Num a, Eq a) => Eq (Poly a) where
  P xs == P ys =
    removeLeadingZeros (reverse xs) == removeLeadingZeros (reverse ys)

removeLeadingZeros :: (Eq a, Num a) => [a] -> [a]
removeLeadingZeros (0 : xs) = removeLeadingZeros xs
removeLeadingZeros xs = xs

请注意,您不必再次reverse来寻找平等(xs == ys <=> reverse xs == reverse ys

这是ghci中的简短测试会话:

λ> let p1 = P[1,2,3,0,0]
λ> let p2 = P[1,2,3]
λ> let p3 = P[1,2,3,0,4]

λ> p1 == p2
True

λ> p1 == p3
False

λ> p2 == p3
False

使用智能构造函数

另一种可能性是不发布P构造函数并在构造时将多项式转换为规范化形式 - 这样做的好处是可以使用deriving Eq

module Poly
       ( Poly, fromList
       ) where

newtype Poly a = P [a]
                 deriving Eq

fromList :: (Num a, Eq a) => [a] -> Poly a
fromList = P . reverse . removeLeadingZeros . reverse

例如

λ> let p1 = fromList [1,2,3,0,0]
λ> let p2 = fromList [1,2,3]

λ> p1 == p2
True

全部隐藏

由于您似乎已经实现了Num (Poly a),您甚至可以从导出中删除fromList - 因此用户必须使用算术运算符来构造多项式。

您基本上只需要导出x

x :: (Eq a, Num a) => Poly a
x = fromList [0,1]

备注

取决于P []是否适用于零多项式,或者在这种情况下您更愿意使用P [0],而您可能希望将removeLeadingZeros重写为

removeLeadingZeros :: (Eq a, Num a) => [a] -> [a]
removeLeadingZeros [0] = [0]
removeLeadingZeros (0 : xs) = removeLeadingZeros xs
removeLeadingZeros xs = xs

或类似的东西

答案 1 :(得分:2)

removeLeadingZeros (0 : xs) = removeLeadingZeros xs removeLeadingZeros xs = xs

反转列表,删除前导零,然后再反转。

(reverse . removeLeadingZeros . reverse) [3, 2, 1, 0, 0, 0]

对两个多项式执行相同的操作,并使用==进行比较。

(暂不考虑,但我认为这是对的。)