{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms       #-}
{-# LANGUAGE QuasiQuotes           #-}

{- |
Module      : Language.Egison.Math.Expr
Licence     : MIT

This module defines the internal representation of mathematic objects such as
polynominals, and some useful patterns.
-}

module Language.Egison.Math.Expr
    ( ScalarData (..)
    , PolyExpr (..)
    , TermExpr (..)
    , Monomial
    , SymbolExpr (..)
    , Printable (..)
    , pattern ZeroExpr
    , pattern SingleSymbol
    , pattern SingleTerm
    , ScalarM (..)
    , TermM (..)
    , SymbolM (..)
    , term
    , termM
    , symbol
    , symbolM
    , func
    , funcM
    , apply
    , applyM
    , quote
    , negQuote
    , negQuoteM
    , equalMonomial
    , equalMonomialM
    , zero
    , zeroM
    , singleTerm
    , singleTermM
    , mathScalarMult
    , mathNegate
    ) where

import           Data.List             (intercalate)
import           Prelude               hiding (foldr, mappend, mconcat)

import           Control.Egison
import           Control.Monad         (MonadPlus (..))

import           Language.Egison.IExpr (Index (..))

--
-- Data
--


data ScalarData
  = Div PolyExpr PolyExpr
 deriving ScalarData -> ScalarData -> Bool
(ScalarData -> ScalarData -> Bool)
-> (ScalarData -> ScalarData -> Bool) -> Eq ScalarData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ScalarData -> ScalarData -> Bool
$c/= :: ScalarData -> ScalarData -> Bool
== :: ScalarData -> ScalarData -> Bool
$c== :: ScalarData -> ScalarData -> Bool
Eq

newtype PolyExpr
  = Plus [TermExpr]

data TermExpr
  = Term Integer Monomial

-- We choose the definition 'monomials' without its coefficients.
-- ex. 2 x^2 y^3 is *not* a monomial. x^2 t^3 is a monomial.
type Monomial = [(SymbolExpr, Integer)]

data SymbolExpr
  = Symbol Id String [Index ScalarData]
  | Apply ScalarData [ScalarData]
  | Quote ScalarData
  | FunctionData ScalarData [ScalarData] [ScalarData] -- fnname argnames args
  deriving SymbolExpr -> SymbolExpr -> Bool
(SymbolExpr -> SymbolExpr -> Bool)
-> (SymbolExpr -> SymbolExpr -> Bool) -> Eq SymbolExpr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SymbolExpr -> SymbolExpr -> Bool
$c/= :: SymbolExpr -> SymbolExpr -> Bool
== :: SymbolExpr -> SymbolExpr -> Bool
$c== :: SymbolExpr -> SymbolExpr -> Bool
Eq

type Id = String

-- Matchers

data ScalarM = ScalarM
instance Matcher ScalarM ScalarData

data TermM = TermM
instance Matcher TermM TermExpr

data SymbolM = SymbolM
instance Matcher SymbolM SymbolExpr

term :: Pattern (PP Integer, PP Monomial) TermM TermExpr (Integer, Monomial)
term :: Pattern
  (PP Integer, PP Monomial) TermM TermExpr (Integer, Monomial)
term (PP Integer, PP Monomial)
_ TermM
_ (Term Integer
a Monomial
mono) = (Integer, Monomial) -> [(Integer, Monomial)]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Integer
a, Monomial
mono)
termM :: TermM -> TermExpr -> (Eql, Multiset (Pair SymbolM Eql))
termM :: TermM -> TermExpr -> (Eql, Multiset (Pair SymbolM Eql))
termM TermM
TermM TermExpr
_ = (Eql
Eql, Pair SymbolM Eql -> Multiset (Pair SymbolM Eql)
forall m. m -> Multiset m
Multiset (SymbolM -> Eql -> Pair SymbolM Eql
forall m1 m2. m1 -> m2 -> Pair m1 m2
Pair SymbolM
SymbolM Eql
Eql))

symbol :: Pattern (PP String) SymbolM SymbolExpr String
symbol :: Pattern (PP String) SymbolM SymbolExpr String
symbol PP String
_ SymbolM
_ (Symbol String
_ String
name []) = String -> [String]
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
name
symbol PP String
_ SymbolM
_ SymbolExpr
_                  = [String]
forall (m :: * -> *) a. MonadPlus m => m a
mzero
symbolM :: SymbolM -> p -> Eql
symbolM :: SymbolM -> p -> Eql
symbolM SymbolM
SymbolM p
_ = Eql
Eql

func :: Pattern (PP ScalarData, PP [ScalarData])
                SymbolM SymbolExpr (ScalarData, [ScalarData])
func :: Pattern
  (PP ScalarData, PP [ScalarData])
  SymbolM
  SymbolExpr
  (ScalarData, [ScalarData])
func (PP ScalarData, PP [ScalarData])
_ SymbolM
_ (FunctionData ScalarData
name [ScalarData]
_ [ScalarData]
args) = (ScalarData, [ScalarData]) -> [(ScalarData, [ScalarData])]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ScalarData
name, [ScalarData]
args)
func (PP ScalarData, PP [ScalarData])
_ SymbolM
_ SymbolExpr
_                             = [(ScalarData, [ScalarData])]
forall (m :: * -> *) a. MonadPlus m => m a
mzero
funcM :: SymbolM -> SymbolExpr -> (ScalarM, List ScalarM)
funcM :: SymbolM -> SymbolExpr -> (ScalarM, List ScalarM)
funcM SymbolM
SymbolM SymbolExpr
_ = (ScalarM
ScalarM, ScalarM -> List ScalarM
forall m. m -> List m
List ScalarM
ScalarM)

apply :: Pattern (PP String, PP [ScalarData]) SymbolM SymbolExpr (String, [ScalarData])
apply :: Pattern
  (PP String, PP [ScalarData])
  SymbolM
  SymbolExpr
  (String, [ScalarData])
apply (PP String, PP [ScalarData])
_ SymbolM
_ (Apply (SingleSymbol (Symbol String
_ String
fn [Index ScalarData]
_)) [ScalarData]
args) = (String, [ScalarData]) -> [(String, [ScalarData])]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
fn, [ScalarData]
args)
apply (PP String, PP [ScalarData])
_ SymbolM
_ SymbolExpr
_                                           = [(String, [ScalarData])]
forall (m :: * -> *) a. MonadPlus m => m a
mzero
applyM :: SymbolM -> p -> (Eql, List ScalarM)
applyM :: SymbolM -> p -> (Eql, List ScalarM)
applyM SymbolM
SymbolM p
_ = (Eql
Eql, ScalarM -> List ScalarM
forall m. m -> List m
List ScalarM
ScalarM)

quote :: Pattern (PP ScalarData) SymbolM SymbolExpr ScalarData
quote :: Pattern (PP ScalarData) SymbolM SymbolExpr ScalarData
quote PP ScalarData
_ SymbolM
_ (Quote ScalarData
m) = ScalarData -> [ScalarData]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ScalarData
m
quote PP ScalarData
_ SymbolM
_ SymbolExpr
_         = [ScalarData]
forall (m :: * -> *) a. MonadPlus m => m a
mzero

negQuote :: Pattern (PP ScalarData) SymbolM SymbolExpr ScalarData
negQuote :: Pattern (PP ScalarData) SymbolM SymbolExpr ScalarData
negQuote PP ScalarData
_ SymbolM
_ (Quote ScalarData
m) = ScalarData -> [ScalarData]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ScalarData -> ScalarData
mathNegate ScalarData
m)
negQuote PP ScalarData
_ SymbolM
_ SymbolExpr
_         = [ScalarData]
forall (m :: * -> *) a. MonadPlus m => m a
mzero
negQuoteM :: SymbolM -> p -> ScalarM
negQuoteM :: SymbolM -> p -> ScalarM
negQuoteM SymbolM
SymbolM p
_ = ScalarM
ScalarM

equalMonomial :: Pattern (PP Integer, PP Monomial) (Multiset (Pair SymbolM Eql)) Monomial (Integer, Monomial)
equalMonomial :: Pattern
  (PP Integer, PP Monomial)
  (Multiset (Pair SymbolM Eql))
  Monomial
  (Integer, Monomial)
equalMonomial (PP Integer
_, VP Monomial
xs) Multiset (Pair SymbolM Eql)
_ Monomial
ys = case Monomial -> Monomial -> Maybe Integer
isEqualMonomial Monomial
xs Monomial
ys of
                                  Just Integer
sgn -> (Integer, Monomial) -> [(Integer, Monomial)]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Integer
sgn, Monomial
xs)
                                  Maybe Integer
Nothing  -> [(Integer, Monomial)]
forall (m :: * -> *) a. MonadPlus m => m a
mzero
equalMonomial (PP Integer, PP Monomial)
_ Multiset (Pair SymbolM Eql)
_ Monomial
_ = [(Integer, Monomial)]
forall (m :: * -> *) a. MonadPlus m => m a
mzero
equalMonomialM :: Multiset (Pair SymbolM Eql) -> p -> (Eql, Multiset (Pair SymbolM Eql))
equalMonomialM :: Multiset (Pair SymbolM Eql)
-> p -> (Eql, Multiset (Pair SymbolM Eql))
equalMonomialM (Multiset (Pair SymbolM
SymbolM Eql
Eql)) p
_ = (Eql
Eql, Pair SymbolM Eql -> Multiset (Pair SymbolM Eql)
forall m. m -> Multiset m
Multiset (SymbolM -> Eql -> Pair SymbolM Eql
forall m1 m2. m1 -> m2 -> Pair m1 m2
Pair SymbolM
SymbolM Eql
Eql))

zero :: Pattern () ScalarM ScalarData ()
zero :: Pattern () ScalarM ScalarData ()
zero ()
_ ScalarM
_ (Div (Plus []) PolyExpr
_) = () -> [()]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
zero ()
_ ScalarM
_ ScalarData
_                 = [()]
forall (m :: * -> *) a. MonadPlus m => m a
mzero
zeroM :: ScalarM -> p -> ()
zeroM :: ScalarM -> p -> ()
zeroM ScalarM
ScalarM p
_ = ()

singleTerm :: Pattern (PP Integer, PP Integer, PP Monomial) ScalarM ScalarData (Integer, Integer, Monomial)
singleTerm :: Pattern
  (PP Integer, PP Integer, PP Monomial)
  ScalarM
  ScalarData
  (Integer, Integer, Monomial)
singleTerm (PP Integer, PP Integer, PP Monomial)
_ ScalarM
_ (Div (Plus [Term Integer
c Monomial
mono]) (Plus [Term Integer
c2 []])) = (Integer, Integer, Monomial) -> [(Integer, Integer, Monomial)]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Integer
c, Integer
c2, Monomial
mono)
singleTerm (PP Integer, PP Integer, PP Monomial)
_ ScalarM
_ ScalarData
_                                              = [(Integer, Integer, Monomial)]
forall (m :: * -> *) a. MonadPlus m => m a
mzero
singleTermM :: ScalarM -> p -> (Eql, Eql, Multiset (Pair SymbolM Eql))
singleTermM :: ScalarM -> p -> (Eql, Eql, Multiset (Pair SymbolM Eql))
singleTermM ScalarM
ScalarM p
_ = (Eql
Eql, Eql
Eql, Pair SymbolM Eql -> Multiset (Pair SymbolM Eql)
forall m. m -> Multiset m
Multiset (SymbolM -> Eql -> Pair SymbolM Eql
forall m1 m2. m1 -> m2 -> Pair m1 m2
Pair SymbolM
SymbolM Eql
Eql))


instance ValuePattern ScalarM ScalarData where
  value :: ScalarData -> Pattern () ScalarM ScalarData ()
value ScalarData
e () ScalarM
ScalarM ScalarData
v = if ScalarData
e ScalarData -> ScalarData -> Bool
forall a. Eq a => a -> a -> Bool
== ScalarData
v then () -> [()]
forall (f :: * -> *) a. Applicative f => a -> f a
pure () else [()]
forall (m :: * -> *) a. MonadPlus m => m a
mzero

instance ValuePattern SymbolM SymbolExpr where
  value :: SymbolExpr -> Pattern () SymbolM SymbolExpr ()
value SymbolExpr
e () SymbolM
SymbolM SymbolExpr
v = if SymbolExpr
e SymbolExpr -> SymbolExpr -> Bool
forall a. Eq a => a -> a -> Bool
== SymbolExpr
v then () -> [()]
forall (f :: * -> *) a. Applicative f => a -> f a
pure () else [()]
forall (m :: * -> *) a. MonadPlus m => m a
mzero


pattern ZeroExpr :: ScalarData
pattern $bZeroExpr :: ScalarData
$mZeroExpr :: forall r. ScalarData -> (Void# -> r) -> (Void# -> r) -> r
ZeroExpr = (Div (Plus []) (Plus [Term 1 []]))

pattern SingleSymbol :: SymbolExpr -> ScalarData
pattern $bSingleSymbol :: SymbolExpr -> ScalarData
$mSingleSymbol :: forall r. ScalarData -> (SymbolExpr -> r) -> (Void# -> r) -> r
SingleSymbol sym = Div (Plus [Term 1 [(sym, 1)]]) (Plus [Term 1 []])

-- Product of a coefficient and a monomial
pattern SingleTerm :: Integer -> Monomial -> ScalarData
pattern $bSingleTerm :: Integer -> Monomial -> ScalarData
$mSingleTerm :: forall r.
ScalarData -> (Integer -> Monomial -> r) -> (Void# -> r) -> r
SingleTerm coeff mono = Div (Plus [Term coeff mono]) (Plus [Term 1 []])

instance Eq PolyExpr where
  Plus [TermExpr]
xs == :: PolyExpr -> PolyExpr -> Bool
== Plus [TermExpr]
ys =
    ((Multiset Eql, [TermExpr]) -> DFS (Multiset Eql, [TermExpr]))
-> [TermExpr]
-> Multiset Eql
-> [(Multiset Eql, [TermExpr]) -> DFS Bool]
-> Bool
forall m t (s :: * -> *) r.
(Matcher m t, MonadSearch s) =>
((m, t) -> s (m, t)) -> t -> m -> [(m, t) -> s r] -> r
match (Multiset Eql, [TermExpr]) -> DFS (Multiset Eql, [TermExpr])
forall a. a -> DFS a
dfs [TermExpr]
ys (Eql -> Multiset Eql
forall m. m -> Multiset m
Multiset Eql
Eql)
      [ [mc| #xs -> True |]
      , [mc| _   -> False |] ]

instance Eq TermExpr where
  Term Integer
a Monomial
xs == :: TermExpr -> TermExpr -> Bool
== Term Integer
b Monomial
ys
    | Integer
a Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
b    = Monomial -> Monomial -> Maybe Integer
isEqualMonomial Monomial
xs Monomial
ys Maybe Integer -> Maybe Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer -> Maybe Integer
forall a. a -> Maybe a
Just Integer
1
    | Integer
a Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== -Integer
b   = Monomial -> Monomial -> Maybe Integer
isEqualMonomial Monomial
xs Monomial
ys Maybe Integer -> Maybe Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer -> Maybe Integer
forall a. a -> Maybe a
Just (-Integer
1)
    | Bool
otherwise = Bool
False

isEqualMonomial :: Monomial -> Monomial -> Maybe Integer
isEqualMonomial :: Monomial -> Monomial -> Maybe Integer
isEqualMonomial Monomial
xs Monomial
ys =
  ((Pair (Multiset (Pair SymbolM Eql)) (Multiset (Pair SymbolM Eql)),
  (Monomial, Monomial))
 -> DFS
      (Pair (Multiset (Pair SymbolM Eql)) (Multiset (Pair SymbolM Eql)),
       (Monomial, Monomial)))
-> (Monomial, Monomial)
-> Pair (Multiset (Pair SymbolM Eql)) (Multiset (Pair SymbolM Eql))
-> [(Pair
       (Multiset (Pair SymbolM Eql)) (Multiset (Pair SymbolM Eql)),
     (Monomial, Monomial))
    -> DFS (Maybe Integer)]
-> Maybe Integer
forall m t (s :: * -> *) r.
(Matcher m t, MonadSearch s) =>
((m, t) -> s (m, t)) -> t -> m -> [(m, t) -> s r] -> r
match (Pair (Multiset (Pair SymbolM Eql)) (Multiset (Pair SymbolM Eql)),
 (Monomial, Monomial))
-> DFS
     (Pair (Multiset (Pair SymbolM Eql)) (Multiset (Pair SymbolM Eql)),
      (Monomial, Monomial))
forall a. a -> DFS a
dfs (Monomial
xs, Monomial
ys) (Multiset (Pair SymbolM Eql)
-> Multiset (Pair SymbolM Eql)
-> Pair (Multiset (Pair SymbolM Eql)) (Multiset (Pair SymbolM Eql))
forall m1 m2. m1 -> m2 -> Pair m1 m2
Pair (Pair SymbolM Eql -> Multiset (Pair SymbolM Eql)
forall m. m -> Multiset m
Multiset (SymbolM -> Eql -> Pair SymbolM Eql
forall m1 m2. m1 -> m2 -> Pair m1 m2
Pair SymbolM
SymbolM Eql
Eql)) (Pair SymbolM Eql -> Multiset (Pair SymbolM Eql)
forall m. m -> Multiset m
Multiset (SymbolM -> Eql -> Pair SymbolM Eql
forall m1 m2. m1 -> m2 -> Pair m1 m2
Pair SymbolM
SymbolM Eql
Eql)))
    [ [mc| ((quote $s, $n) : $xss, (negQuote #s, #n) : $yss) ->
             case isEqualMonomial xss yss of
               Nothing -> Nothing
               Just sgn -> return (if even n then sgn else - sgn) |]
    , [mc| (($x, $n) : $xss, (#x, #n) : $yss) -> isEqualMonomial xss yss |]
    , [mc| ([], []) -> return 1 |]
    , [mc| _ -> Nothing |]
    ]

--
--  Arithmetic operations
--

mathScalarMult :: Integer -> ScalarData -> ScalarData
mathScalarMult :: Integer -> ScalarData -> ScalarData
mathScalarMult Integer
c (Div PolyExpr
m PolyExpr
n) = PolyExpr -> PolyExpr -> ScalarData
Div (Integer -> PolyExpr -> PolyExpr
f Integer
c PolyExpr
m) PolyExpr
n
  where
    f :: Integer -> PolyExpr -> PolyExpr
f Integer
c (Plus [TermExpr]
ts) = [TermExpr] -> PolyExpr
Plus ((TermExpr -> TermExpr) -> [TermExpr] -> [TermExpr]
forall a b. (a -> b) -> [a] -> [b]
map (\(Term Integer
a Monomial
xs) -> Integer -> Monomial -> TermExpr
Term (Integer
c Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
a) Monomial
xs) [TermExpr]
ts)

mathNegate :: ScalarData -> ScalarData
mathNegate :: ScalarData -> ScalarData
mathNegate = Integer -> ScalarData -> ScalarData
mathScalarMult (-Integer
1)

--
-- Pretty printing
--

class Printable a where
  isAtom :: a -> Bool
  pretty :: a -> String

pretty' :: Printable a => a -> String
pretty' :: a -> String
pretty' a
e | a -> Bool
forall a. Printable a => a -> Bool
isAtom a
e = a -> String
forall a. Printable a => a -> String
pretty a
e
pretty' a
e            = String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Printable a => a -> String
pretty a
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"

instance Printable ScalarData where
  isAtom :: ScalarData -> Bool
isAtom (Div PolyExpr
p (Plus [Term Integer
1 []])) = PolyExpr -> Bool
forall a. Printable a => a -> Bool
isAtom PolyExpr
p
  isAtom ScalarData
_                          = Bool
False

  pretty :: ScalarData -> String
pretty (Div PolyExpr
p1 (Plus [Term Integer
1 []])) = PolyExpr -> String
forall a. Printable a => a -> String
pretty PolyExpr
p1
  pretty (Div PolyExpr
p1 PolyExpr
p2)                 = PolyExpr -> String
pretty'' PolyExpr
p1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" / " String -> String -> String
forall a. [a] -> [a] -> [a]
++ PolyExpr -> String
forall a. Printable a => a -> String
pretty' PolyExpr
p2
    where
      pretty'' :: PolyExpr -> String
      pretty'' :: PolyExpr -> String
pretty'' p :: PolyExpr
p@(Plus [TermExpr
_]) = PolyExpr -> String
forall a. Printable a => a -> String
pretty PolyExpr
p
      pretty'' PolyExpr
p            = String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PolyExpr -> String
forall a. Printable a => a -> String
pretty PolyExpr
p String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"

instance Printable PolyExpr where
  isAtom :: PolyExpr -> Bool
isAtom (Plus [])           = Bool
True
  isAtom (Plus [Term Integer
_ []])  = Bool
True
  isAtom (Plus [Term Integer
1 [(SymbolExpr, Integer)
_]]) = Bool
True
  isAtom PolyExpr
_                   = Bool
False

  pretty :: PolyExpr -> String
pretty (Plus []) = String
"0"
  pretty (Plus (TermExpr
t:[TermExpr]
ts)) = TermExpr -> String
forall a. Printable a => a -> String
pretty TermExpr
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ (TermExpr -> String) -> [TermExpr] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap TermExpr -> String
withSign [TermExpr]
ts
    where
      withSign :: TermExpr -> String
withSign (Term Integer
a Monomial
xs) | Integer
a Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = String
" - " String -> String -> String
forall a. [a] -> [a] -> [a]
++ TermExpr -> String
forall a. Printable a => a -> String
pretty (Integer -> Monomial -> TermExpr
Term (- Integer
a) Monomial
xs)
      withSign TermExpr
t                   = String
" + " String -> String -> String
forall a. [a] -> [a] -> [a]
++ TermExpr -> String
forall a. Printable a => a -> String
pretty TermExpr
t

instance Printable SymbolExpr where
  isAtom :: SymbolExpr -> Bool
isAtom Symbol{}     = Bool
True
  isAtom (Apply ScalarData
_ []) = Bool
True
  isAtom Quote{}      = Bool
True
  isAtom SymbolExpr
_            = Bool
False

  pretty :: SymbolExpr -> String
pretty (Symbol String
_ (Char
':':Char
':':Char
':':String
_) []) = String
"#"
  pretty (Symbol String
_ String
s [])               = String
s
  pretty (Symbol String
_ String
s [Index ScalarData]
js)               = String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Index ScalarData -> String) -> [Index ScalarData] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Index ScalarData -> String
forall a. Show a => a -> String
show [Index ScalarData]
js
  pretty (Apply ScalarData
fn [ScalarData]
mExprs)             = [String] -> String
unwords ((ScalarData -> String) -> [ScalarData] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ScalarData -> String
forall a. Printable a => a -> String
pretty' (ScalarData
fn ScalarData -> [ScalarData] -> [ScalarData]
forall a. a -> [a] -> [a]
: [ScalarData]
mExprs))
  pretty (Quote ScalarData
mExprs)                = String
"`" String -> String -> String
forall a. [a] -> [a] -> [a]
++ ScalarData -> String
forall a. Printable a => a -> String
pretty' ScalarData
mExprs
  pretty (FunctionData ScalarData
name [ScalarData]
_ [ScalarData]
_)    = ScalarData -> String
forall a. Printable a => a -> String
pretty ScalarData
name

instance Printable TermExpr where
  isAtom :: TermExpr -> Bool
isAtom (Term Integer
_ [])  = Bool
True
  isAtom (Term Integer
1 [(SymbolExpr, Integer)
_]) = Bool
True
  isAtom TermExpr
_            = Bool
False

  pretty :: TermExpr -> String
pretty (Term Integer
a [])    = Integer -> String
forall a. Show a => a -> String
show Integer
a
  pretty (Term Integer
1 Monomial
xs)    = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" * " (((SymbolExpr, Integer) -> String) -> Monomial -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (SymbolExpr, Integer) -> String
prettyPoweredSymbol Monomial
xs)
  pretty (Term (-1) Monomial
xs) = String
"- " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" * " (((SymbolExpr, Integer) -> String) -> Monomial -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (SymbolExpr, Integer) -> String
prettyPoweredSymbol Monomial
xs)
  pretty (Term Integer
a Monomial
xs)    = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" * " (Integer -> String
forall a. Show a => a -> String
show Integer
a String -> [String] -> [String]
forall a. a -> [a] -> [a]
: ((SymbolExpr, Integer) -> String) -> Monomial -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (SymbolExpr, Integer) -> String
prettyPoweredSymbol Monomial
xs)

prettyPoweredSymbol :: (SymbolExpr, Integer) -> String
prettyPoweredSymbol :: (SymbolExpr, Integer) -> String
prettyPoweredSymbol (SymbolExpr
x, Integer
1) = SymbolExpr -> String
forall a. Show a => a -> String
show SymbolExpr
x
prettyPoweredSymbol (SymbolExpr
x, Integer
n) = SymbolExpr -> String
forall a. Printable a => a -> String
pretty' SymbolExpr
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"^" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
n

instance Show ScalarData where
  show :: ScalarData -> String
show = ScalarData -> String
forall a. Printable a => a -> String
pretty

instance Show PolyExpr where
  show :: PolyExpr -> String
show = PolyExpr -> String
forall a. Printable a => a -> String
pretty

instance Show TermExpr where
  show :: TermExpr -> String
show = TermExpr -> String
forall a. Printable a => a -> String
pretty

instance Show SymbolExpr where
  show :: SymbolExpr -> String
show = SymbolExpr -> String
forall a. Printable a => a -> String
pretty

instance {-# OVERLAPPING #-} Show (Index ScalarData) where
  show :: Index ScalarData -> String
show (Sup ScalarData
i)    = String
"~" String -> String -> String
forall a. [a] -> [a] -> [a]
++ ScalarData -> String
forall a. Printable a => a -> String
pretty' ScalarData
i
  show (Sub ScalarData
i)    = String
"_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ ScalarData -> String
forall a. Printable a => a -> String
pretty' ScalarData
i
  show (SupSub ScalarData
i) = String
"~_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ ScalarData -> String
forall a. Printable a => a -> String
pretty' ScalarData
i
  show (DF Integer
_ Integer
_)   = String
""
  show (User ScalarData
i)   = String
"|" String -> String -> String
forall a. [a] -> [a] -> [a]
++ ScalarData -> String
forall a. Printable a => a -> String
pretty' ScalarData
i