{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Math.Algebra.MultiPol
  ( Polynomial() 
  , Monomial(..)
  , lone
  , constant
  , terms
  , (*^)
  , (^+^)
  , (^-^)
  , (^*^)
  , (^**^)
  , evalPoly
  , prettyPol
  )
  where
import qualified Algebra.Additive as AlgAdd
import qualified Algebra.Module   as AlgMod
import qualified Algebra.Ring     as AlgRing
import           Data.Foldable    ( toList )
import           Data.Function    ( on )
import           Data.List        ( sortBy, groupBy )
import qualified Data.Sequence    as S
import           Data.Sequence    ( Seq, (><), (|>) )
import           Data.Text        ( Text, pack, intercalate, cons, snoc, append, unpack )
import           Data.Tuple.Extra ( (&&&) )

infixr 7 *^

infixl 6 ^+^, ^-^

infixl 7 ^*^ 

infixr 8 ^**^


data Monomial a = Monomial 
  { 
    forall a. Monomial a -> a
coefficient :: a, 
    forall a. Monomial a -> Seq Int
powers      :: Seq Int
  }
    deriving (Int -> Monomial a -> ShowS
forall a. Show a => Int -> Monomial a -> ShowS
forall a. Show a => [Monomial a] -> ShowS
forall a. Show a => Monomial a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Monomial a] -> ShowS
$cshowList :: forall a. Show a => [Monomial a] -> ShowS
show :: Monomial a -> String
$cshow :: forall a. Show a => Monomial a -> String
showsPrec :: Int -> Monomial a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Monomial a -> ShowS
Show, Monomial a -> Monomial a -> Bool
forall a. Eq a => Monomial a -> Monomial a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Monomial a -> Monomial a -> Bool
$c/= :: forall a. Eq a => Monomial a -> Monomial a -> Bool
== :: Monomial a -> Monomial a -> Bool
$c== :: forall a. Eq a => Monomial a -> Monomial a -> Bool
Eq)

data Polynomial a = Zero
                  | M (Monomial a)
                  | Polynomial a :+: Polynomial a
                  | Polynomial a :*: Polynomial a
                    deriving (Int -> Polynomial a -> ShowS
forall a. Show a => Int -> Polynomial a -> ShowS
forall a. Show a => [Polynomial a] -> ShowS
forall a. Show a => Polynomial a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Polynomial a] -> ShowS
$cshowList :: forall a. Show a => [Polynomial a] -> ShowS
show :: Polynomial a -> String
$cshow :: forall a. Show a => Polynomial a -> String
showsPrec :: Int -> Polynomial a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Polynomial a -> ShowS
Show)
instance (AlgRing.C a, Eq a) => Eq (Polynomial a) where
  Polynomial a
p == :: Polynomial a -> Polynomial a -> Bool
== Polynomial a
q = forall a b. (a -> b) -> [a] -> [b]
map forall a. Monomial a -> a
coefficient (forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
toListOfMonomials forall a b. (a -> b) -> a -> b
$ Polynomial a
p forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
^-^ Polynomial a
q) forall a. Eq a => a -> a -> Bool
== forall a. Monoid a => a
mempty
instance (AlgRing.C a, Eq a) => AlgAdd.C (Polynomial a) where
  Polynomial a
p + :: Polynomial a -> Polynomial a -> Polynomial a
+ Polynomial a
q = forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
addPolys Polynomial a
p Polynomial a
q
  zero :: Polynomial a
zero = forall a. Polynomial a
Zero
  negate :: Polynomial a -> Polynomial a
negate = forall a. (C a, Eq a) => Polynomial a -> Polynomial a
negatePol
instance (AlgRing.C a, Eq a) => AlgMod.C a (Polynomial a) where
  a
lambda *> :: a -> Polynomial a -> Polynomial a
*> Polynomial a
p = forall a. (C a, Eq a) => a -> Polynomial a -> Polynomial a
scalePol a
lambda Polynomial a
p
instance (AlgRing.C a, Eq a) => AlgRing.C (Polynomial a) where
  Polynomial a
p * :: Polynomial a -> Polynomial a -> Polynomial a
* Polynomial a
q = forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
multiplyPols Polynomial a
p Polynomial a
q
  one :: Polynomial a
one = forall a. (C a, Eq a) => Int -> Polynomial a
lone Int
0

addPolys :: (AlgRing.C a, Eq a) => Polynomial a -> Polynomial a -> Polynomial a
addPolys :: forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
addPolys Polynomial a
p Polynomial a
q = forall a. (C a, Eq a) => Polynomial a -> Polynomial a
toCanonicalForm forall a b. (a -> b) -> a -> b
$ Polynomial a
p forall a. Polynomial a -> Polynomial a -> Polynomial a
:+: Polynomial a
q

-- | Addition of two polynomials
(^+^) :: (AlgRing.C a, Eq a) => Polynomial a -> Polynomial a -> Polynomial a
^+^ :: forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
(^+^) Polynomial a
p Polynomial a
q = Polynomial a
p forall a. C a => a -> a -> a
AlgAdd.+ Polynomial a
q

negatePol :: (AlgRing.C a, Eq a) => Polynomial a -> Polynomial a
negatePol :: forall a. (C a, Eq a) => Polynomial a -> Polynomial a
negatePol Polynomial a
pol = case Polynomial a
pol of 
  Polynomial a
Zero -> forall a. Polynomial a
Zero
  M Monomial a
monomial -> forall a. Monomial a -> Polynomial a
M (forall a1. (C a1, Eq a1) => Monomial a1 -> Monomial a1
negateMonomial Monomial a
monomial)
  Polynomial a
pol -> forall a. (C a, Eq a) => [Monomial a] -> Polynomial a
fromListOfMonomials (forall a b. (a -> b) -> [a] -> [b]
map forall a1. (C a1, Eq a1) => Monomial a1 -> Monomial a1
negateMonomial (forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
toListOfMonomials Polynomial a
pol))
  where
    negateMonomial :: forall a1. (AlgRing.C a1, Eq a1) => Monomial a1 -> Monomial a1
    negateMonomial :: forall a1. (C a1, Eq a1) => Monomial a1 -> Monomial a1
negateMonomial Monomial a1
monomial = Monomial { 
      coefficient :: a1
coefficient = forall a. C a => a -> a
AlgAdd.negate (forall a. Monomial a -> a
coefficient Monomial a1
monomial), 
      powers :: Seq Int
powers = forall a. Monomial a -> Seq Int
powers Monomial a1
monomial
    }

-- | Substraction
(^-^) :: (AlgRing.C a, Eq a) => Polynomial a -> Polynomial a -> Polynomial a
^-^ :: forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
(^-^) Polynomial a
p Polynomial a
q = Polynomial a
p forall a. C a => a -> a -> a
AlgAdd.- Polynomial a
q

multiplyPols :: (AlgRing.C a, Eq a) => Polynomial a -> Polynomial a -> Polynomial a
multiplyPols :: forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
multiplyPols Polynomial a
p Polynomial a
q = forall a. (C a, Eq a) => Polynomial a -> Polynomial a
toCanonicalForm forall a b. (a -> b) -> a -> b
$ Polynomial a
p forall a. Polynomial a -> Polynomial a -> Polynomial a
:*: Polynomial a
q

-- | Multiply two polynomials
(^*^) :: (AlgRing.C a, Eq a) => Polynomial a -> Polynomial a -> Polynomial a
^*^ :: forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
(^*^) Polynomial a
p Polynomial a
q = Polynomial a
p forall a. C a => a -> a -> a
AlgRing.* Polynomial a
q

-- | Power of a polynomial
(^**^) :: (AlgRing.C a, Eq a) => Polynomial a -> Int -> Polynomial a
^**^ :: forall a. (C a, Eq a) => Polynomial a -> Int -> Polynomial a
(^**^) Polynomial a
p Int
n = forall a. C a => [a] -> a
AlgRing.product (forall a. Int -> a -> [a]
replicate Int
n Polynomial a
p) 

scalePol :: (AlgRing.C a, Eq a) => a -> Polynomial a -> Polynomial a
scalePol :: forall a. (C a, Eq a) => a -> Polynomial a -> Polynomial a
scalePol a
lambda Polynomial a
pol = if a
lambda forall a. Eq a => a -> a -> Bool
== forall a. C a => a
AlgAdd.zero
  then forall a. Polynomial a
Zero 
  else case Polynomial a
pol of
    Polynomial a
Zero -> forall a. Polynomial a
Zero 
    M Monomial a
monomial -> forall a. Monomial a -> Polynomial a
M (Monomial a -> Monomial a
scaleMonomial Monomial a
monomial)
    Polynomial a
p :+: Polynomial a
q -> if Polynomial a
p forall a. Eq a => a -> a -> Bool
/= forall a. Polynomial a
Zero Bool -> Bool -> Bool
&& Polynomial a
q forall a. Eq a => a -> a -> Bool
/= forall a. Polynomial a
Zero
      then forall a. (C a, Eq a) => a -> Polynomial a -> Polynomial a
scalePol a
lambda Polynomial a
p forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
^+^ forall a. (C a, Eq a) => a -> Polynomial a -> Polynomial a
scalePol a
lambda Polynomial a
q
      else if Polynomial a
p forall a. Eq a => a -> a -> Bool
== forall a. Polynomial a
Zero
        then forall a. (C a, Eq a) => a -> Polynomial a -> Polynomial a
scalePol a
lambda Polynomial a
q
        else forall a. (C a, Eq a) => a -> Polynomial a -> Polynomial a
scalePol a
lambda Polynomial a
p
    Polynomial a
p :*: Polynomial a
q -> if Polynomial a
p forall a. Eq a => a -> a -> Bool
== forall a. Polynomial a
Zero Bool -> Bool -> Bool
|| Polynomial a
q forall a. Eq a => a -> a -> Bool
== forall a. Polynomial a
Zero
      then forall a. Polynomial a
Zero
      else forall a. (C a, Eq a) => a -> Polynomial a -> Polynomial a
scalePol a
lambda Polynomial a
p forall a.
(C a, Eq a) =>
Polynomial a -> Polynomial a -> Polynomial a
^*^ Polynomial a
q
  where
    scaleMonomial :: Monomial a -> Monomial a
scaleMonomial Monomial a
monomial = Monomial {
                                coefficient :: a
coefficient = a
lambda forall a. C a => a -> a -> a
AlgRing.* forall a. Monomial a -> a
coefficient Monomial a
monomial
                              , powers :: Seq Int
powers = forall a. Monomial a -> Seq Int
powers Monomial a
monomial
                             }

-- | Scale polynomial by a scalar
(*^) :: (AlgRing.C a, Eq a) => a -> Polynomial a -> Polynomial a
*^ :: forall a. (C a, Eq a) => a -> Polynomial a -> Polynomial a
(*^) a
lambda Polynomial a
pol = a
lambda forall a v. C a v => a -> v -> v
AlgMod.*> Polynomial a
pol 

-- | Polynomial x_n
lone :: (AlgRing.C a, Eq a) => Int -> Polynomial a
lone :: forall a. (C a, Eq a) => Int -> Polynomial a
lone Int
n = forall a. Monomial a -> Polynomial a
M (forall a. a -> Seq Int -> Monomial a
Monomial forall a. C a => a
AlgRing.one Seq Int
pows)
  where
    pows :: Seq Int
pows = if Int
n forall a. Eq a => a -> a -> Bool
== Int
0 
      then 
        forall a. Seq a
S.empty 
      else 
        forall a. Int -> a -> Seq a
S.replicate (Int
n forall a. Num a => a -> a -> a
- Int
1) forall a. C a => a
AlgAdd.zero forall a. Seq a -> a -> Seq a
|> forall a. C a => a
AlgRing.one

-- | Constant polynomial
constant :: (AlgRing.C a, Eq a) => a -> Polynomial a
constant :: forall a. (C a, Eq a) => a -> Polynomial a
constant a
x = forall a. Monomial a -> Polynomial a
M (forall a. a -> Seq Int -> Monomial a
Monomial a
x forall a. Seq a
S.empty)

growSequence :: Seq Int -> Int -> Seq Int 
growSequence :: Seq Int -> Int -> Seq Int
growSequence Seq Int
s Int
n = Seq Int
s forall a. Seq a -> Seq a -> Seq a
>< Seq Int
t
  where 
    m :: Int
m = forall a. Seq a -> Int
S.length Seq Int
s 
    t :: Seq Int
t = forall a. Int -> a -> Seq a
S.replicate (Int
n forall a. Num a => a -> a -> a
- Int
m) Int
0
 
grow :: Int -> Monomial a -> Monomial a
grow :: forall a. Int -> Monomial a -> Monomial a
grow Int
n Monomial a
monom = forall a. a -> Seq Int -> Monomial a
Monomial (forall a. Monomial a -> a
coefficient Monomial a
monom) (Seq Int -> Int -> Seq Int
growSequence (forall a. Monomial a -> Seq Int
powers Monomial a
monom) Int
n)

nvariables :: Monomial a -> Int
nvariables :: forall a. Monomial a -> Int
nvariables Monomial a
monom = forall a. Seq a -> Int
S.length forall a b. (a -> b) -> a -> b
$ forall a. Monomial a -> Seq Int
powers Monomial a
monom

-- Build a polynomial from a list of monomials
fromListOfMonomials :: (AlgRing.C a, Eq a) => [Monomial a] -> Polynomial a
fromListOfMonomials :: forall a. (C a, Eq a) => [Monomial a] -> Polynomial a
fromListOfMonomials [Monomial a]
ms = if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Monomial a]
ms
                            then forall a. Polynomial a
Zero
                            else forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 forall a. Polynomial a -> Polynomial a -> Polynomial a
(:+:) (forall a b. (a -> b) -> [a] -> [b]
map forall a. Monomial a -> Polynomial a
M [Monomial a]
ms)

multMonomial :: (AlgRing.C a, Eq a) => Monomial a -> Monomial a -> Monomial a
multMonomial :: forall a. (C a, Eq a) => Monomial a -> Monomial a -> Monomial a
multMonomial (Monomial a
ca Seq Int
powsa) (Monomial a
cb Seq Int
powsb) =
  forall a. a -> Seq Int -> Monomial a
Monomial (a
ca forall a. C a => a -> a -> a
AlgRing.* a
cb) (forall a b c. (a -> b -> c) -> Seq a -> Seq b -> Seq c
S.zipWith forall a. Num a => a -> a -> a
(+) Seq Int
powsa' Seq Int
powsb')
  where
    n :: Int
n = forall a. Ord a => a -> a -> a
max (forall a. Seq a -> Int
S.length Seq Int
powsa) (forall a. Seq a -> Int
S.length Seq Int
powsb)
    powsa' :: Seq Int
powsa' = Seq Int -> Int -> Seq Int
growSequence Seq Int
powsa Int
n
    powsb' :: Seq Int
powsb' = Seq Int -> Int -> Seq Int
growSequence Seq Int
powsb Int
n

-- Polynomial to list of monomials
toListOfMonomials :: (AlgRing.C a, Eq a) => Polynomial a -> [Monomial a]
toListOfMonomials :: forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
toListOfMonomials Polynomial a
pol = case Polynomial a
pol of
  Polynomial a
Zero -> []
  M Monomial a
monomial -> if forall a. Monomial a -> a
coefficient Monomial a
monomial forall a. Eq a => a -> a -> Bool
== forall a. C a => a
AlgAdd.zero then [] else [Monomial a
monomial]
  Polynomial a
p :+: Polynomial a
q -> forall {a}. [Monomial a] -> [Monomial a]
harmonize forall a b. (a -> b) -> a -> b
$ forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
toListOfMonomials Polynomial a
p forall a. [a] -> [a] -> [a]
++ forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
toListOfMonomials Polynomial a
q
  Polynomial a
p :*: Polynomial a
q -> forall {a}. [Monomial a] -> [Monomial a]
harmonize forall a b. (a -> b) -> a -> b
$ [forall a. (C a, Eq a) => Monomial a -> Monomial a -> Monomial a
multMonomial Monomial a
monoa Monomial a
monob | Monomial a
monoa <- forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
toListOfMonomials Polynomial a
p,
                                                     Monomial a
monob <- forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
toListOfMonomials Polynomial a
q]
  where
    harmonize :: [Monomial a] -> [Monomial a]
harmonize [Monomial a]
ms = forall a b. (a -> b) -> [a] -> [b]
map (forall a. Int -> Monomial a -> Monomial a
grow (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (forall a b. (a -> b) -> [a] -> [b]
map forall a. Monomial a -> Int
nvariables [Monomial a]
ms))) [Monomial a]
ms

-- | List of the terms of a polynomial 
terms :: (AlgRing.C a, Eq a) => Polynomial a -> [Monomial a]
terms :: forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
terms Polynomial a
pol = case Polynomial a
pol of
  Polynomial a
Zero -> []
  M Monomial a
monomial -> [Monomial a
monomial]
  Polynomial a
p :+: Polynomial a
q -> forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
terms Polynomial a
p forall a. [a] -> [a] -> [a]
++ forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
terms Polynomial a
q
  Polynomial a
p :*: Polynomial a
q -> forall a. HasCallStack => String -> a
error String
"that should not happen"

-- Polynomial to list of monomials, grouping the monomials with same powers
simplifiedListOfMonomials :: (AlgRing.C a, Eq a) => Polynomial a -> [Monomial a]
simplifiedListOfMonomials :: forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
simplifiedListOfMonomials Polynomial a
pol = forall a b. (a -> b) -> [a] -> [b]
map (forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 forall a. (C a, Eq a) => Monomial a -> Monomial a -> Monomial a
addMonomials) [[Monomial a]]
groups
  where
    groups :: [[Monomial a]]
groups = forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (forall a. Eq a => a -> a -> Bool
(==) forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall a. Monomial a -> Seq Int
powers)
             (forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (forall a. Ord a => a -> a -> Ordering
compare forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall a. Monomial a -> Seq Int
powers) (forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
toListOfMonomials Polynomial a
pol))
    addMonomials :: forall a1. (AlgRing.C a1, Eq a1) => Monomial a1 -> Monomial a1 -> Monomial a1
    addMonomials :: forall a. (C a, Eq a) => Monomial a -> Monomial a -> Monomial a
addMonomials Monomial a1
monoa Monomial a1
monob = Monomial {
                                coefficient :: a1
coefficient = forall a. Monomial a -> a
coefficient Monomial a1
monoa forall a. C a => a -> a -> a
AlgAdd.+ forall a. Monomial a -> a
coefficient Monomial a1
monob
                              , powers :: Seq Int
powers = forall a. Monomial a -> Seq Int
powers Monomial a1
monoa
                              }

-- Canonical form of a polynomial (sum of monomials with distinct powers)
toCanonicalForm :: (AlgRing.C a, Eq a) => Polynomial a -> Polynomial a
toCanonicalForm :: forall a. (C a, Eq a) => Polynomial a -> Polynomial a
toCanonicalForm = forall a. (C a, Eq a) => [Monomial a] -> Polynomial a
fromListOfMonomials forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
simplifiedListOfMonomials

evalMonomial :: (AlgRing.C a, Eq a) => [a] -> Monomial a -> a
evalMonomial :: forall a. (C a, Eq a) => [a] -> Monomial a -> a
evalMonomial [a]
xyz Monomial a
monomial =
  forall a. Monomial a -> a
coefficient Monomial a
monomial forall a. C a => a -> a -> a
AlgRing.* forall a. C a => [a] -> a
AlgRing.product (forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. C a => a -> Integer -> a
(AlgRing.^) [a]
xyz [Integer]
pows)
  where
    pows :: [Integer]
pows = forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Monomial a -> Seq Int
powers Monomial a
monomial)

-- | Evaluates a polynomial
evalPoly :: (AlgRing.C a, Eq a) => Polynomial a -> [a] -> a
evalPoly :: forall a. (C a, Eq a) => Polynomial a -> [a] -> a
evalPoly Polynomial a
pol [a]
xyz = case Polynomial a
pol of
  Polynomial a
Zero -> forall a. C a => a
AlgAdd.zero
  M Monomial a
mono -> forall a. (C a, Eq a) => [a] -> Monomial a -> a
evalMonomial [a]
xyz Monomial a
mono
  Polynomial a
p :+: Polynomial a
q -> forall a. (C a, Eq a) => Polynomial a -> [a] -> a
evalPoly Polynomial a
p [a]
xyz forall a. C a => a -> a -> a
AlgAdd.+ forall a. (C a, Eq a) => Polynomial a -> [a] -> a
evalPoly Polynomial a
q [a]
xyz
  Polynomial a
p :*: Polynomial a
q -> forall a. HasCallStack => String -> a
error String
"that should not happen" --evalPoly p xyz AlgRing.* evalPoly q xyz

prettyPowers :: String -> [Int] -> Text
prettyPowers :: String -> [Int] -> Text
prettyPowers String
var [Int]
pows = Text -> Text -> Text
append (String -> Text
pack String
x) (Char -> Text -> Text
cons Char
'(' forall a b. (a -> b) -> a -> b
$ Text -> Char -> Text
snoc Text
string Char
')') 
  where
    x :: String
x = String
" " forall a. [a] -> [a] -> [a]
++ String
var forall a. [a] -> [a] -> [a]
++ String
"^"
    string :: Text
string = Text -> [Text] -> Text
intercalate (String -> Text
pack String
", ") (forall a b. (a -> b) -> [a] -> [b]
map (String -> Text
pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show) [Int]
pows)

-- | Pretty form of a polynomial
prettyPol :: (AlgRing.C a, Eq a) => (a -> String) -> String -> Polynomial a -> String
prettyPol :: forall a.
(C a, Eq a) =>
(a -> String) -> String -> Polynomial a -> String
prettyPol a -> String
prettyCoef String
var Polynomial a
p = Text -> String
unpack forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> Text
intercalate (String -> Text
pack String
" + ") [Text]
stringTerms
  where
    stringTerms :: [Text]
stringTerms = forall a b. (a -> b) -> [a] -> [b]
map Monomial a -> Text
stringTerm (forall a. (C a, Eq a) => Polynomial a -> [Monomial a]
terms Polynomial a
p)
    stringTerm :: Monomial a -> Text
stringTerm Monomial a
term = 
      Text -> Text -> Text
append (Text -> Char -> Text
snoc (Text -> Char -> Text
snoc (Char -> Text -> Text
cons Char
'(' forall a b. (a -> b) -> a -> b
$ Text -> Char -> Text
snoc Text
stringCoef Char
')') Char
' ') Char
'*') (String -> [Int] -> Text
prettyPowers String
var [Int]
pows)
      where
        pows :: [Int]
pows = forall (t :: * -> *) a. Foldable t => t a -> [a]
toList forall a b. (a -> b) -> a -> b
$ forall a. Monomial a -> Seq Int
powers Monomial a
term
        stringCoef :: Text
stringCoef = String -> Text
pack forall a b. (a -> b) -> a -> b
$ a -> String
prettyCoef (forall a. Monomial a -> a
coefficient Monomial a
term)