module GHC.TypeLits.Normalise.SOP
(
Symbol (..)
, Product (..)
, SOP (..)
, reduceExp
, mergeS
, mergeP
, mergeSOPAdd
, mergeSOPMul
, normaliseExp
)
where
import Data.Either (partitionEithers)
import Data.List (sort)
import Outputable (Outputable (..), (<+>), text, hcat, integer, punctuate)
data Symbol v c
= I Integer
| C c
| E (SOP v c) (Product v c)
| V v
deriving (Symbol v c -> Symbol v c -> Bool
(Symbol v c -> Symbol v c -> Bool)
-> (Symbol v c -> Symbol v c -> Bool) -> Eq (Symbol v c)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall v c. (Eq c, Eq v) => Symbol v c -> Symbol v c -> Bool
/= :: Symbol v c -> Symbol v c -> Bool
$c/= :: forall v c. (Eq c, Eq v) => Symbol v c -> Symbol v c -> Bool
== :: Symbol v c -> Symbol v c -> Bool
$c== :: forall v c. (Eq c, Eq v) => Symbol v c -> Symbol v c -> Bool
Eq,Eq (Symbol v c)
Eq (Symbol v c) =>
(Symbol v c -> Symbol v c -> Ordering)
-> (Symbol v c -> Symbol v c -> Bool)
-> (Symbol v c -> Symbol v c -> Bool)
-> (Symbol v c -> Symbol v c -> Bool)
-> (Symbol v c -> Symbol v c -> Bool)
-> (Symbol v c -> Symbol v c -> Symbol v c)
-> (Symbol v c -> Symbol v c -> Symbol v c)
-> Ord (Symbol v c)
Symbol v c -> Symbol v c -> Bool
Symbol v c -> Symbol v c -> Ordering
Symbol v c -> Symbol v c -> Symbol v c
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall v c. (Ord c, Ord v) => Eq (Symbol v c)
forall v c. (Ord c, Ord v) => Symbol v c -> Symbol v c -> Bool
forall v c. (Ord c, Ord v) => Symbol v c -> Symbol v c -> Ordering
forall v c.
(Ord c, Ord v) =>
Symbol v c -> Symbol v c -> Symbol v c
min :: Symbol v c -> Symbol v c -> Symbol v c
$cmin :: forall v c.
(Ord c, Ord v) =>
Symbol v c -> Symbol v c -> Symbol v c
max :: Symbol v c -> Symbol v c -> Symbol v c
$cmax :: forall v c.
(Ord c, Ord v) =>
Symbol v c -> Symbol v c -> Symbol v c
>= :: Symbol v c -> Symbol v c -> Bool
$c>= :: forall v c. (Ord c, Ord v) => Symbol v c -> Symbol v c -> Bool
> :: Symbol v c -> Symbol v c -> Bool
$c> :: forall v c. (Ord c, Ord v) => Symbol v c -> Symbol v c -> Bool
<= :: Symbol v c -> Symbol v c -> Bool
$c<= :: forall v c. (Ord c, Ord v) => Symbol v c -> Symbol v c -> Bool
< :: Symbol v c -> Symbol v c -> Bool
$c< :: forall v c. (Ord c, Ord v) => Symbol v c -> Symbol v c -> Bool
compare :: Symbol v c -> Symbol v c -> Ordering
$ccompare :: forall v c. (Ord c, Ord v) => Symbol v c -> Symbol v c -> Ordering
$cp1Ord :: forall v c. (Ord c, Ord v) => Eq (Symbol v c)
Ord)
newtype Product v c = P { Product v c -> [Symbol v c]
unP :: [Symbol v c] }
deriving (Product v c -> Product v c -> Bool
(Product v c -> Product v c -> Bool)
-> (Product v c -> Product v c -> Bool) -> Eq (Product v c)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall v c. (Eq c, Eq v) => Product v c -> Product v c -> Bool
/= :: Product v c -> Product v c -> Bool
$c/= :: forall v c. (Eq c, Eq v) => Product v c -> Product v c -> Bool
== :: Product v c -> Product v c -> Bool
$c== :: forall v c. (Eq c, Eq v) => Product v c -> Product v c -> Bool
Eq)
instance (Ord v, Ord c) => Ord (Product v c) where
compare :: Product v c -> Product v c -> Ordering
compare (P [x :: Symbol v c
x]) (P [y :: Symbol v c
y]) = Symbol v c -> Symbol v c -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Symbol v c
x Symbol v c
y
compare (P [_]) (P (_:_)) = Ordering
LT
compare (P (_:_)) (P [_]) = Ordering
GT
compare (P xs :: [Symbol v c]
xs) (P ys :: [Symbol v c]
ys) = [Symbol v c] -> [Symbol v c] -> Ordering
forall a. Ord a => a -> a -> Ordering
compare [Symbol v c]
xs [Symbol v c]
ys
newtype SOP v c = S { SOP v c -> [Product v c]
unS :: [Product v c] }
deriving (Eq (SOP v c)
Eq (SOP v c) =>
(SOP v c -> SOP v c -> Ordering)
-> (SOP v c -> SOP v c -> Bool)
-> (SOP v c -> SOP v c -> Bool)
-> (SOP v c -> SOP v c -> Bool)
-> (SOP v c -> SOP v c -> Bool)
-> (SOP v c -> SOP v c -> SOP v c)
-> (SOP v c -> SOP v c -> SOP v c)
-> Ord (SOP v c)
SOP v c -> SOP v c -> Bool
SOP v c -> SOP v c -> Ordering
SOP v c -> SOP v c -> SOP v c
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall v c. (Ord v, Ord c) => Eq (SOP v c)
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> Bool
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> Ordering
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
min :: SOP v c -> SOP v c -> SOP v c
$cmin :: forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
max :: SOP v c -> SOP v c -> SOP v c
$cmax :: forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
>= :: SOP v c -> SOP v c -> Bool
$c>= :: forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> Bool
> :: SOP v c -> SOP v c -> Bool
$c> :: forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> Bool
<= :: SOP v c -> SOP v c -> Bool
$c<= :: forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> Bool
< :: SOP v c -> SOP v c -> Bool
$c< :: forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> Bool
compare :: SOP v c -> SOP v c -> Ordering
$ccompare :: forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> Ordering
$cp1Ord :: forall v c. (Ord v, Ord c) => Eq (SOP v c)
Ord)
instance (Eq v, Eq c) => Eq (SOP v c) where
(S []) == :: SOP v c -> SOP v c -> Bool
== (S [P [I 0]]) = Bool
True
(S [P [I 0]]) == (S []) = Bool
True
(S ps1 :: [Product v c]
ps1) == (S ps2 :: [Product v c]
ps2) = [Product v c]
ps1 [Product v c] -> [Product v c] -> Bool
forall a. Eq a => a -> a -> Bool
== [Product v c]
ps2
instance (Outputable v, Outputable c) => Outputable (SOP v c) where
ppr :: SOP v c -> SDoc
ppr = [SDoc] -> SDoc
hcat ([SDoc] -> SDoc) -> (SOP v c -> [SDoc]) -> SOP v c -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SDoc -> [SDoc] -> [SDoc]
punctuate (String -> SDoc
text " + ") ([SDoc] -> [SDoc]) -> (SOP v c -> [SDoc]) -> SOP v c -> [SDoc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Product v c -> SDoc) -> [Product v c] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map Product v c -> SDoc
forall a. Outputable a => a -> SDoc
ppr ([Product v c] -> [SDoc])
-> (SOP v c -> [Product v c]) -> SOP v c -> [SDoc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SOP v c -> [Product v c]
forall v c. SOP v c -> [Product v c]
unS
instance (Outputable v, Outputable c) => Outputable (Product v c) where
ppr :: Product v c -> SDoc
ppr = [SDoc] -> SDoc
hcat ([SDoc] -> SDoc) -> (Product v c -> [SDoc]) -> Product v c -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SDoc -> [SDoc] -> [SDoc]
punctuate (String -> SDoc
text " * ") ([SDoc] -> [SDoc])
-> (Product v c -> [SDoc]) -> Product v c -> [SDoc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Symbol v c -> SDoc) -> [Symbol v c] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map Symbol v c -> SDoc
forall a. Outputable a => a -> SDoc
ppr ([Symbol v c] -> [SDoc])
-> (Product v c -> [Symbol v c]) -> Product v c -> [SDoc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Product v c -> [Symbol v c]
forall v c. Product v c -> [Symbol v c]
unP
instance (Outputable v, Outputable c) => Outputable (Symbol v c) where
ppr :: Symbol v c -> SDoc
ppr (I i :: Integer
i) = Integer -> SDoc
integer Integer
i
ppr (C c :: c
c) = c -> SDoc
forall a. Outputable a => a -> SDoc
ppr c
c
ppr (V s :: v
s) = v -> SDoc
forall a. Outputable a => a -> SDoc
ppr v
s
ppr (E b :: SOP v c
b e :: Product v c
e) = case (SOP v c -> SDoc
forall v c. (Outputable v, Outputable c) => SOP v c -> SDoc
pprSimple SOP v c
b, SOP v c -> SDoc
forall v c. (Outputable v, Outputable c) => SOP v c -> SDoc
pprSimple ([Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [Product v c
e])) of
(bS :: SDoc
bS,eS :: SDoc
eS) -> SDoc
bS SDoc -> SDoc -> SDoc
<+> String -> SDoc
text "^" SDoc -> SDoc -> SDoc
<+> SDoc
eS
where
pprSimple :: SOP a c -> SDoc
pprSimple (S [P [I i :: Integer
i]]) = Integer -> SDoc
integer Integer
i
pprSimple (S [P [V v :: a
v]]) = a -> SDoc
forall a. Outputable a => a -> SDoc
ppr a
v
pprSimple sop :: SOP a c
sop = String -> SDoc
text "(" SDoc -> SDoc -> SDoc
<+> SOP a c -> SDoc
forall a. Outputable a => a -> SDoc
ppr SOP a c
sop SDoc -> SDoc -> SDoc
<+> String -> SDoc
text ")"
mergeWith :: (a -> a -> Either a a) -> [a] -> [a]
mergeWith :: (a -> a -> Either a a) -> [a] -> [a]
mergeWith _ [] = []
mergeWith op :: a -> a -> Either a a
op (f :: a
f:fs :: [a]
fs) = case [Either a a] -> ([a], [a])
forall a b. [Either a b] -> ([a], [b])
partitionEithers ([Either a a] -> ([a], [a])) -> [Either a a] -> ([a], [a])
forall a b. (a -> b) -> a -> b
$ (a -> Either a a) -> [a] -> [Either a a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a -> Either a a
`op` a
f) [a]
fs of
([],_) -> a
f a -> [a] -> [a]
forall a. a -> [a] -> [a]
: (a -> a -> Either a a) -> [a] -> [a]
forall a. (a -> a -> Either a a) -> [a] -> [a]
mergeWith a -> a -> Either a a
op [a]
fs
(updated :: [a]
updated,untouched :: [a]
untouched) -> (a -> a -> Either a a) -> [a] -> [a]
forall a. (a -> a -> Either a a) -> [a] -> [a]
mergeWith a -> a -> Either a a
op ([a]
updated [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
untouched)
reduceExp :: (Ord v, Ord c) => Symbol v c -> Symbol v c
reduceExp :: Symbol v c -> Symbol v c
reduceExp (E _ (P [(I 0)])) = Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I 1
reduceExp (E (S [P [I 0]]) _ ) = Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I 0
reduceExp (E (S [P [(I i :: Integer
i)]]) (P [(I j :: Integer
j)]))
| Integer
j Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= 0 = Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I (Integer
i Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
j)
reduceExp (E (S [P [(E k :: SOP v c
k i :: Product v c
i)]]) j :: Product v c
j) = case SOP v c -> SOP v c -> SOP v c
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
normaliseExp SOP v c
k ([Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [Product v c
e]) of
(S [P [s :: Symbol v c
s]]) -> Symbol v c
s
_ -> SOP v c -> Product v c -> Symbol v c
forall v c. SOP v c -> Product v c -> Symbol v c
E SOP v c
k Product v c
e
where
e :: Product v c
e = [Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P ([Symbol v c] -> Product v c)
-> ([Symbol v c] -> [Symbol v c]) -> [Symbol v c] -> Product v c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Symbol v c] -> [Symbol v c]
forall a. Ord a => [a] -> [a]
sort ([Symbol v c] -> [Symbol v c])
-> ([Symbol v c] -> [Symbol v c]) -> [Symbol v c] -> [Symbol v c]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Symbol v c -> Symbol v c) -> [Symbol v c] -> [Symbol v c]
forall a b. (a -> b) -> [a] -> [b]
map Symbol v c -> Symbol v c
forall v c. (Ord v, Ord c) => Symbol v c -> Symbol v c
reduceExp ([Symbol v c] -> Product v c) -> [Symbol v c] -> Product v c
forall a b. (a -> b) -> a -> b
$ (Symbol v c -> Symbol v c -> Either (Symbol v c) (Symbol v c))
-> [Symbol v c] -> [Symbol v c]
forall a. (a -> a -> Either a a) -> [a] -> [a]
mergeWith Symbol v c -> Symbol v c -> Either (Symbol v c) (Symbol v c)
forall v c.
(Ord v, Ord c) =>
Symbol v c -> Symbol v c -> Either (Symbol v c) (Symbol v c)
mergeS (Product v c -> [Symbol v c]
forall v c. Product v c -> [Symbol v c]
unP Product v c
i [Symbol v c] -> [Symbol v c] -> [Symbol v c]
forall a. [a] -> [a] -> [a]
++ Product v c -> [Symbol v c]
forall v c. Product v c -> [Symbol v c]
unP Product v c
j)
reduceExp s :: Symbol v c
s = Symbol v c
s
mergeS :: (Ord v, Ord c) => Symbol v c -> Symbol v c
-> Either (Symbol v c) (Symbol v c)
mergeS :: Symbol v c -> Symbol v c -> Either (Symbol v c) (Symbol v c)
mergeS (I i :: Integer
i) (I j :: Integer
j) = Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left (Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
j))
mergeS (I 1) r :: Symbol v c
r = Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left Symbol v c
r
mergeS l :: Symbol v c
l (I 1) = Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left Symbol v c
l
mergeS (I 0) _ = Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left (Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I 0)
mergeS _ (I 0) = Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left (Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I 0)
mergeS s :: Symbol v c
s (E (S [P [s' :: Symbol v c
s']]) (P [I i :: Integer
i]))
| Symbol v c
s Symbol v c -> Symbol v c -> Bool
forall a. Eq a => a -> a -> Bool
== Symbol v c
s'
= Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left (SOP v c -> Product v c -> Symbol v c
forall v c. SOP v c -> Product v c -> Symbol v c
E ([Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Symbol v c
s']]) ([Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ 1)]))
mergeS (E (S [P [s' :: Symbol v c
s']]) (P [I i :: Integer
i])) s :: Symbol v c
s
| Symbol v c
s Symbol v c -> Symbol v c -> Bool
forall a. Eq a => a -> a -> Bool
== Symbol v c
s'
= Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left (SOP v c -> Product v c -> Symbol v c
forall v c. SOP v c -> Product v c -> Symbol v c
E ([Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Symbol v c
s']]) ([Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ 1)]))
mergeS (E (S [P [I i :: Integer
i]]) p :: Product v c
p) (E (S [P [I j :: Integer
j]]) p' :: Product v c
p')
| Product v c
p Product v c -> Product v c -> Bool
forall a. Eq a => a -> a -> Bool
== Product v c
p'
= Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left (SOP v c -> Product v c -> Symbol v c
forall v c. SOP v c -> Product v c -> Symbol v c
E ([Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I (Integer
iInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
j)]]) Product v c
p)
mergeS l :: Symbol v c
l r :: Symbol v c
r
| Symbol v c
l Symbol v c -> Symbol v c -> Bool
forall a. Eq a => a -> a -> Bool
== Symbol v c
r
= case SOP v c -> SOP v c -> SOP v c
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
normaliseExp ([Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Symbol v c
l]]) ([Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I 2]]) of
(S [P [e :: Symbol v c
e]]) -> Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left Symbol v c
e
_ -> Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. b -> Either a b
Right Symbol v c
l
mergeS (E s1 :: SOP v c
s1 (P p1 :: [Symbol v c]
p1)) (E s2 :: SOP v c
s2 (P (I i :: Integer
i:p2 :: [Symbol v c]
p2)))
| Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== (-1)
, SOP v c
s1 SOP v c -> SOP v c -> Bool
forall a. Eq a => a -> a -> Bool
== SOP v c
s2
, [Symbol v c]
p1 [Symbol v c] -> [Symbol v c] -> Bool
forall a. Eq a => a -> a -> Bool
== [Symbol v c]
p2
= Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left (Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I 1)
mergeS (E s1 :: SOP v c
s1 (P (I i :: Integer
i:p1 :: [Symbol v c]
p1))) (E s2 :: SOP v c
s2 (P p2 :: [Symbol v c]
p2))
| Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== (-1)
, SOP v c
s1 SOP v c -> SOP v c -> Bool
forall a. Eq a => a -> a -> Bool
== SOP v c
s2
, [Symbol v c]
p1 [Symbol v c] -> [Symbol v c] -> Bool
forall a. Eq a => a -> a -> Bool
== [Symbol v c]
p2
= Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. a -> Either a b
Left (Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I 1)
mergeS l :: Symbol v c
l _ = Symbol v c -> Either (Symbol v c) (Symbol v c)
forall a b. b -> Either a b
Right Symbol v c
l
mergeP :: (Eq v, Eq c) => Product v c -> Product v c
-> Either (Product v c) (Product v c)
mergeP :: Product v c -> Product v c -> Either (Product v c) (Product v c)
mergeP (P ((I i :: Integer
i):is :: [Symbol v c]
is)) (P ((I j :: Integer
j):js :: [Symbol v c]
js))
| [Symbol v c]
is [Symbol v c] -> [Symbol v c] -> Bool
forall a. Eq a => a -> a -> Bool
== [Symbol v c]
js = Product v c -> Either (Product v c) (Product v c)
forall a b. a -> Either a b
Left (Product v c -> Either (Product v c) (Product v c))
-> ([Symbol v c] -> Product v c)
-> [Symbol v c]
-> Either (Product v c) (Product v c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P ([Symbol v c] -> Either (Product v c) (Product v c))
-> [Symbol v c] -> Either (Product v c) (Product v c)
forall a b. (a -> b) -> a -> b
$ (Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
j)) Symbol v c -> [Symbol v c] -> [Symbol v c]
forall a. a -> [a] -> [a]
: [Symbol v c]
is
mergeP (P ((I i :: Integer
i):is :: [Symbol v c]
is)) (P js :: [Symbol v c]
js)
| [Symbol v c]
is [Symbol v c] -> [Symbol v c] -> Bool
forall a. Eq a => a -> a -> Bool
== [Symbol v c]
js = Product v c -> Either (Product v c) (Product v c)
forall a b. a -> Either a b
Left (Product v c -> Either (Product v c) (Product v c))
-> ([Symbol v c] -> Product v c)
-> [Symbol v c]
-> Either (Product v c) (Product v c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P ([Symbol v c] -> Either (Product v c) (Product v c))
-> [Symbol v c] -> Either (Product v c) (Product v c)
forall a b. (a -> b) -> a -> b
$ (Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ 1)) Symbol v c -> [Symbol v c] -> [Symbol v c]
forall a. a -> [a] -> [a]
: [Symbol v c]
is
mergeP (P is :: [Symbol v c]
is) (P ((I j :: Integer
j):js :: [Symbol v c]
js))
| [Symbol v c]
is [Symbol v c] -> [Symbol v c] -> Bool
forall a. Eq a => a -> a -> Bool
== [Symbol v c]
js = Product v c -> Either (Product v c) (Product v c)
forall a b. a -> Either a b
Left (Product v c -> Either (Product v c) (Product v c))
-> ([Symbol v c] -> Product v c)
-> [Symbol v c]
-> Either (Product v c) (Product v c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P ([Symbol v c] -> Either (Product v c) (Product v c))
-> [Symbol v c] -> Either (Product v c) (Product v c)
forall a b. (a -> b) -> a -> b
$ (Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I (Integer
j Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ 1)) Symbol v c -> [Symbol v c] -> [Symbol v c]
forall a. a -> [a] -> [a]
: [Symbol v c]
is
mergeP (P is :: [Symbol v c]
is) (P js :: [Symbol v c]
js)
| [Symbol v c]
is [Symbol v c] -> [Symbol v c] -> Bool
forall a. Eq a => a -> a -> Bool
== [Symbol v c]
js = Product v c -> Either (Product v c) (Product v c)
forall a b. a -> Either a b
Left (Product v c -> Either (Product v c) (Product v c))
-> ([Symbol v c] -> Product v c)
-> [Symbol v c]
-> Either (Product v c) (Product v c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P ([Symbol v c] -> Either (Product v c) (Product v c))
-> [Symbol v c] -> Either (Product v c) (Product v c)
forall a b. (a -> b) -> a -> b
$ (Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I 2) Symbol v c -> [Symbol v c] -> [Symbol v c]
forall a. a -> [a] -> [a]
: [Symbol v c]
is
| Bool
otherwise = Product v c -> Either (Product v c) (Product v c)
forall a b. b -> Either a b
Right (Product v c -> Either (Product v c) (Product v c))
-> Product v c -> Either (Product v c) (Product v c)
forall a b. (a -> b) -> a -> b
$ [Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Symbol v c]
is
normaliseExp :: (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
normaliseExp :: SOP v c -> SOP v c -> SOP v c
normaliseExp b :: SOP v c
b (S [P [I 1]]) = SOP v c
b
normaliseExp b :: SOP v c
b@(S [P [V _]]) (S [e :: Product v c
e]) = [Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [SOP v c -> Product v c -> Symbol v c
forall v c. SOP v c -> Product v c -> Symbol v c
E SOP v c
b Product v c
e]]
normaliseExp b :: SOP v c
b@(S [P [_]]) (S [e :: Product v c
e@(P [_])]) = [Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Symbol v c -> Symbol v c
forall v c. (Ord v, Ord c) => Symbol v c -> Symbol v c
reduceExp (SOP v c -> Product v c -> Symbol v c
forall v c. SOP v c -> Product v c -> Symbol v c
E SOP v c
b Product v c
e)]]
normaliseExp b :: SOP v c
b (S [P [(I i :: Integer
i)]]) =
(SOP v c -> SOP v c -> SOP v c) -> [SOP v c] -> SOP v c
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 SOP v c -> SOP v c -> SOP v c
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
mergeSOPMul (Int -> SOP v c -> [SOP v c]
forall a. Int -> a -> [a]
replicate (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
i) SOP v c
b)
normaliseExp b :: SOP v c
b (S [P (e :: Symbol v c
e@(I i :: Integer
i):es :: [Symbol v c]
es)]) | Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= 0 =
SOP v c -> SOP v c -> SOP v c
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
normaliseExp (SOP v c -> SOP v c -> SOP v c
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
normaliseExp SOP v c
b ([Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Symbol v c
e]])) ([Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Symbol v c]
es])
normaliseExp b :: SOP v c
b (S [e :: Product v c
e]) = [Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [Symbol v c -> Symbol v c
forall v c. (Ord v, Ord c) => Symbol v c -> Symbol v c
reduceExp (SOP v c -> Product v c -> Symbol v c
forall v c. SOP v c -> Product v c -> Symbol v c
E SOP v c
b Product v c
e)]]
normaliseExp b :: SOP v c
b (S e :: [Product v c]
e) = (SOP v c -> SOP v c -> SOP v c) -> [SOP v c] -> SOP v c
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 SOP v c -> SOP v c -> SOP v c
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
mergeSOPMul ((Product v c -> SOP v c) -> [Product v c] -> [SOP v c]
forall a b. (a -> b) -> [a] -> [b]
map (SOP v c -> SOP v c -> SOP v c
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
normaliseExp SOP v c
b (SOP v c -> SOP v c)
-> (Product v c -> SOP v c) -> Product v c -> SOP v c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S ([Product v c] -> SOP v c)
-> (Product v c -> [Product v c]) -> Product v c -> SOP v c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Product v c -> [Product v c] -> [Product v c]
forall a. a -> [a] -> [a]
:[])) [Product v c]
e)
zeroP :: Product v c -> Bool
zeroP :: Product v c -> Bool
zeroP (P ((I 0):_)) = Bool
True
zeroP _ = Bool
False
mkNonEmpty :: SOP v c -> SOP v c
mkNonEmpty :: SOP v c -> SOP v c
mkNonEmpty (S []) = [Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S [[Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P [(Integer -> Symbol v c
forall v c. Integer -> Symbol v c
I 0)]]
mkNonEmpty s :: SOP v c
s = SOP v c
s
simplifySOP :: (Ord v, Ord c) => SOP v c -> SOP v c
simplifySOP :: SOP v c -> SOP v c
simplifySOP = (SOP v c -> SOP v c) -> SOP v c -> SOP v c
forall t. Eq t => (t -> t) -> t -> t
repeatF SOP v c -> SOP v c
go
where
go :: SOP v c -> SOP v c
go = SOP v c -> SOP v c
forall v c. SOP v c -> SOP v c
mkNonEmpty
(SOP v c -> SOP v c) -> (SOP v c -> SOP v c) -> SOP v c -> SOP v c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S
([Product v c] -> SOP v c)
-> (SOP v c -> [Product v c]) -> SOP v c -> SOP v c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Product v c] -> [Product v c]
forall a. Ord a => [a] -> [a]
sort ([Product v c] -> [Product v c])
-> (SOP v c -> [Product v c]) -> SOP v c -> [Product v c]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Product v c -> Bool) -> [Product v c] -> [Product v c]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Product v c -> Bool) -> Product v c -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Product v c -> Bool
forall v c. Product v c -> Bool
zeroP)
([Product v c] -> [Product v c])
-> (SOP v c -> [Product v c]) -> SOP v c -> [Product v c]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Product v c -> Product v c -> Either (Product v c) (Product v c))
-> [Product v c] -> [Product v c]
forall a. (a -> a -> Either a a) -> [a] -> [a]
mergeWith Product v c -> Product v c -> Either (Product v c) (Product v c)
forall v c.
(Eq v, Eq c) =>
Product v c -> Product v c -> Either (Product v c) (Product v c)
mergeP
([Product v c] -> [Product v c])
-> (SOP v c -> [Product v c]) -> SOP v c -> [Product v c]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Product v c -> Product v c) -> [Product v c] -> [Product v c]
forall a b. (a -> b) -> [a] -> [b]
map ([Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P ([Symbol v c] -> Product v c)
-> (Product v c -> [Symbol v c]) -> Product v c -> Product v c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Symbol v c] -> [Symbol v c]
forall a. Ord a => [a] -> [a]
sort ([Symbol v c] -> [Symbol v c])
-> (Product v c -> [Symbol v c]) -> Product v c -> [Symbol v c]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Symbol v c -> Symbol v c) -> [Symbol v c] -> [Symbol v c]
forall a b. (a -> b) -> [a] -> [b]
map Symbol v c -> Symbol v c
forall v c. (Ord v, Ord c) => Symbol v c -> Symbol v c
reduceExp ([Symbol v c] -> [Symbol v c])
-> (Product v c -> [Symbol v c]) -> Product v c -> [Symbol v c]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Symbol v c -> Symbol v c -> Either (Symbol v c) (Symbol v c))
-> [Symbol v c] -> [Symbol v c]
forall a. (a -> a -> Either a a) -> [a] -> [a]
mergeWith Symbol v c -> Symbol v c -> Either (Symbol v c) (Symbol v c)
forall v c.
(Ord v, Ord c) =>
Symbol v c -> Symbol v c -> Either (Symbol v c) (Symbol v c)
mergeS ([Symbol v c] -> [Symbol v c])
-> (Product v c -> [Symbol v c]) -> Product v c -> [Symbol v c]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Product v c -> [Symbol v c]
forall v c. Product v c -> [Symbol v c]
unP)
([Product v c] -> [Product v c])
-> (SOP v c -> [Product v c]) -> SOP v c -> [Product v c]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SOP v c -> [Product v c]
forall v c. SOP v c -> [Product v c]
unS
repeatF :: (t -> t) -> t -> t
repeatF f :: t -> t
f x :: t
x =
let x' :: t
x' = t -> t
f t
x
in if t
x' t -> t -> Bool
forall a. Eq a => a -> a -> Bool
== t
x
then t
x
else (t -> t) -> t -> t
repeatF t -> t
f t
x'
{-# INLINEABLE simplifySOP #-}
mergeSOPAdd :: (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
mergeSOPAdd :: SOP v c -> SOP v c -> SOP v c
mergeSOPAdd (S sop1 :: [Product v c]
sop1) (S sop2 :: [Product v c]
sop2) = SOP v c -> SOP v c
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c
simplifySOP (SOP v c -> SOP v c) -> SOP v c -> SOP v c
forall a b. (a -> b) -> a -> b
$ [Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S ([Product v c]
sop1 [Product v c] -> [Product v c] -> [Product v c]
forall a. [a] -> [a] -> [a]
++ [Product v c]
sop2)
{-# INLINEABLE mergeSOPAdd #-}
mergeSOPMul :: (Ord v, Ord c) => SOP v c -> SOP v c -> SOP v c
mergeSOPMul :: SOP v c -> SOP v c -> SOP v c
mergeSOPMul (S sop1 :: [Product v c]
sop1) (S sop2 :: [Product v c]
sop2)
= SOP v c -> SOP v c
forall v c. (Ord v, Ord c) => SOP v c -> SOP v c
simplifySOP
(SOP v c -> SOP v c)
-> ([Product v c] -> SOP v c) -> [Product v c] -> SOP v c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Product v c] -> SOP v c
forall v c. [Product v c] -> SOP v c
S
([Product v c] -> SOP v c) -> [Product v c] -> SOP v c
forall a b. (a -> b) -> a -> b
$ (Product v c -> [Product v c]) -> [Product v c] -> [Product v c]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((Product v c -> Product v c -> Product v c)
-> [Product v c] -> [Product v c] -> [Product v c]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\p1 :: Product v c
p1 p2 :: Product v c
p2 -> [Symbol v c] -> Product v c
forall v c. [Symbol v c] -> Product v c
P (Product v c -> [Symbol v c]
forall v c. Product v c -> [Symbol v c]
unP Product v c
p1 [Symbol v c] -> [Symbol v c] -> [Symbol v c]
forall a. [a] -> [a] -> [a]
++ Product v c -> [Symbol v c]
forall v c. Product v c -> [Symbol v c]
unP Product v c
p2)) [Product v c]
sop1 ([Product v c] -> [Product v c])
-> (Product v c -> [Product v c]) -> Product v c -> [Product v c]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Product v c -> [Product v c]
forall a. a -> [a]
repeat) [Product v c]
sop2
{-# INLINEABLE mergeSOPMul #-}