1

I want to be able to order Polynomes with comparing first by lenght (degree), second by coefficient. Polynomes are list of doubles with [1,2,3] = 3x²+2x+1 . But if there is a zero as last element it should be dropped, so I wrote a function doing that called realPolynom. realPolynom [1,2,3,0] = [1,2,3] Now, my Ord instance looks like:

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

realLength is just Length of polynom without zeros as last.

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

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

pol2list is Polynom p = p

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

Problem is:

  • [0,2,0] < [0,2,3] true, which is good

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

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

  • [0,2,0] == [0,2] false, which is not good! should be equal!

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
Krismu
  • 503
  • 4
  • 14
  • Why are you reversing the polynoms as lists? Also, `reverse $ pol2list $ realPolynom b` is usually more clear than `reverse (pol2list (realPolynom b)))`. – Mephy May 19 '14 at 12:27
  • I agree, looks clearer. I am doing it, as ist needs to compare last elemts first, and my own datatype cannot be reversed – Krismu May 19 '14 at 12:31
  • Have you tried using `compare [0,2,0] [0,2]` instead of `==`? – Mephy May 19 '14 at 12:32
  • 1
    Just a side note: you could define `compare = comparing realLength <> comparing (reverse . pol2list . realPolynom)`, where `<>` is an alias for `mappend` from `Data.Monoid` and monoids in play are `a -> b` and `Ordering`. – fizruk May 19 '14 at 12:34
  • 6
    Where is your Eq instance? – n. m. could be an AI May 19 '14 at 12:39
  • @Merphy yes, compare `[0,2,0] [0,2] = EQ`. So shouldnt it give TRUE with `==`? @fizruk thanks, I'll def have a look at that – Krismu May 19 '14 at 12:41
  • @n.m. it's `datatype ... deriving (Show,Eq)` – Krismu May 19 '14 at 12:43
  • 1
    @Krismu there's your problem. Don't derive Eq, implement it atop your Ord instance. – Louis Wasserman May 19 '14 at 12:50
  • You should write your own `EQ instance` ... The derived one doesn't know anything about your `Ord` instance. – felix-eku May 19 '14 at 12:50
  • I tried that already resulting `error:no memory` making GHCi to crash though it could compile and load the .hs without problem. The code was `instance Eq Polynom where a == b = (realPolynom a) == (realPolynom b)` – Krismu May 19 '14 at 12:55

3 Answers3

7

Instead of deriving Eq, you should probably write

instance Eq Polynom where
  a == b = compare a b == EQ
Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
4

The best solution might be to ensure that no leading zeroes ever turn up in the first place. I.e. instead of ever building polynomes manually from lists, you feed them to a "smart constructor" that eats away zeroes before packing the Polynome data type.

May seem a bit of a OO-ish thing to do, but sometimes this kind of encapsulation is just the way to go, even in functional languages.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • Not in the least OO-ish. After all, what do modules like Data.Map or Data.Ratio do? Exactly this: hiding implementation behind a façade of functions! – ach May 19 '14 at 14:56
0

Something like this should work:

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

Unfortunately, in this case the derived Eq instance is not the intended one.

chi
  • 111,837
  • 3
  • 133
  • 218
  • Thanks again, so what I tried was `x==y = (realPolynom x) == (realPolynom y)` causing GHCi to crash. Works with your fix now, I didnt see that again I am comparing Polynomes in my instance... – Krismu May 19 '14 at 13:03