方程上的Haskell Ord实例悖论



我希望能够排序多项式,首先按长度(度)比较,其次按系数。多项式是具有[1,2,3] = 3x²+2x+1的双精度序列。但是如果最后一个元素是0,它应该被删除,所以我写了一个函数,叫做realPolynomrealPolynom [1,2,3,0] = [1,2,3]现在,我的Ord实例看起来像:

instance Ord Polynom where                                  
    compare a b = compare ((realLength a), reverse (pol2list (realPolynom a))) ((realLength b), reverse (pol2list (realPolynom b)))

realLength为无零多边形的长度。

pLength :: Polynom -> Int       
pLength (Polynom(a)) = length a
realLength :: Polynom -> Int                        
realLength a = pLength(realPolynom(a))

pol2listPolynom p = p

pol2list :: Polynom -> [Double]
pol2list (Polynom p) = p 

问题是:

  • [0,2,0] < [0,2,3] true,这是好的

  • [0,2,0] < [0,2] false, also good

  • [0,2,0] > [0,2] false, also good

  • [0,2,0] == [0,2] false,这是不好的!应该是平等的!

与其推导Eq,不如写

instance Eq Polynom where
  a == b = compare a b == EQ

最好的解决方案可能是确保从一开始就不出现前导零。也就是说,你不需要从列表中手动构建多项式,而是将它们提供给一个"智能构造函数",它会在打包Polynome数据类型之前吃掉零。

可能看起来有点像oo,但有时这种封装就是要走的路,即使在函数式语言中也是如此。

应该这样做:

instance Eq Polynom where
    x == y = pol2list (realPolynom x) == pol2list (realPolynom y)

不幸的是,在这种情况下,派生的Eq实例不是预期的。

最新更新