-- |'normalize' takes a polynomial and combines monomials with the same variables and the constant factors e.g.
--
-- >>> normalize (Polynomial [Monomial 1 ["x"], Monomial 3 [], Monomial 2 ["x"], Monomial 1 ["y"], Monomial (-2) []]
--  [ 1.0 ] + [ 3.0 ]*x + [ 1.0 ]*y
--
normalize :: Polynomial -> Polynomial
normalize (Polynomial ms) = Polynomial (map sumMonomials groups)
    where groups = groupBy sameVars $ sortBy variables (zero (dimension (Polynomial ms)):ms)
          variables (Monomial _ a) (Monomial _ b) = compare (sort a) (sort b)

-- | 'sumMononmials' takes a list of 'Monomial's and sums up the coeffiecients. This only works if every 'Monomial' contains
-- excactly the same variables or none if its a constant factor
normalize :: Polynomial -> Polynomial
normalize (Polynomial ms) = Polynomial (map sumMonomials groups)
    where groups = groupBy sameVars $ sortBy variables (zero (dimension (Polynomial ms)):ms)
          variables (Monomial _ a) (Monomial _ b) = compare (sort a) (sort b)

-- | 'sumMononmials' takes a list of 'Monomial's and sums up the coeffiecients. This only works if every 'Monomial' contains
-- excactly the same variables or none if its a constant factor
normalize (Polynomial ms) = Polynomial (map sumMonomials groups)
    where groups = groupBy sameVars $ sortBy variables (zero (dimension (Polynomial ms)):ms)
          variables (Monomial _ a) (Monomial _ b) = compare (sort a) (sort b)

-- | 'sumMononmials' takes a list of 'Monomial's and sums up the coeffiecients. This only works if every 'Monomial' contains
-- excactly the same variables or none if its a constant factor