module GroupPresentation.Element (
    Signed(..),
    Element,
    element,
    (^~),
    isPositive,
    getGenerator,
    EWord,
    module GroupPresentation.Generator,
  ) where

import GroupPresentation.Generator

infix 9 ^~

data Signed a =
      Positive { Signed a -> a
unSigned :: a }
    | Negative { unSigned :: a }
    deriving (Signed a -> Signed a -> Bool
(Signed a -> Signed a -> Bool)
-> (Signed a -> Signed a -> Bool) -> Eq (Signed a)
forall a. Eq a => Signed a -> Signed a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Signed a -> Signed a -> Bool
$c/= :: forall a. Eq a => Signed a -> Signed a -> Bool
== :: Signed a -> Signed a -> Bool
$c== :: forall a. Eq a => Signed a -> Signed a -> Bool
Eq, Eq (Signed a)
Eq (Signed a)
-> (Signed a -> Signed a -> Ordering)
-> (Signed a -> Signed a -> Bool)
-> (Signed a -> Signed a -> Bool)
-> (Signed a -> Signed a -> Bool)
-> (Signed a -> Signed a -> Bool)
-> (Signed a -> Signed a -> Signed a)
-> (Signed a -> Signed a -> Signed a)
-> Ord (Signed a)
Signed a -> Signed a -> Bool
Signed a -> Signed a -> Ordering
Signed a -> Signed a -> Signed a
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 a. Ord a => Eq (Signed a)
forall a. Ord a => Signed a -> Signed a -> Bool
forall a. Ord a => Signed a -> Signed a -> Ordering
forall a. Ord a => Signed a -> Signed a -> Signed a
min :: Signed a -> Signed a -> Signed a
$cmin :: forall a. Ord a => Signed a -> Signed a -> Signed a
max :: Signed a -> Signed a -> Signed a
$cmax :: forall a. Ord a => Signed a -> Signed a -> Signed a
>= :: Signed a -> Signed a -> Bool
$c>= :: forall a. Ord a => Signed a -> Signed a -> Bool
> :: Signed a -> Signed a -> Bool
$c> :: forall a. Ord a => Signed a -> Signed a -> Bool
<= :: Signed a -> Signed a -> Bool
$c<= :: forall a. Ord a => Signed a -> Signed a -> Bool
< :: Signed a -> Signed a -> Bool
$c< :: forall a. Ord a => Signed a -> Signed a -> Bool
compare :: Signed a -> Signed a -> Ordering
$ccompare :: forall a. Ord a => Signed a -> Signed a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Signed a)
Ord)

instance Functor Signed where
    fmap :: (a -> b) -> Signed a -> Signed b
fmap a -> b
f (Positive a
x) = b -> Signed b
forall a. a -> Signed a
Positive (b -> Signed b) -> b -> Signed b
forall a b. (a -> b) -> a -> b
$ a -> b
f a
x
    fmap a -> b
f (Negative a
x) = b -> Signed b
forall a. a -> Signed a
Negative (b -> Signed b) -> b -> Signed b
forall a b. (a -> b) -> a -> b
$ a -> b
f a
x

instance Applicative Signed where
    pure :: a -> Signed a
pure = a -> Signed a
forall a. a -> Signed a
Positive
    (Positive a -> b
f) <*> :: Signed (a -> b) -> Signed a -> Signed b
<*> (Positive a
x) = b -> Signed b
forall a. a -> Signed a
Positive (a -> b
f a
x)
    (Positive a -> b
f) <*> (Negative a
x) = b -> Signed b
forall a. a -> Signed a
Negative (a -> b
f a
x)
    (Negative a -> b
f) <*> (Positive a
x) = b -> Signed b
forall a. a -> Signed a
Negative (a -> b
f a
x)
    (Negative a -> b
f) <*> (Negative a
x) = b -> Signed b
forall a. a -> Signed a
Positive (a -> b
f a
x)

instance Foldable Signed where
    foldr :: (a -> b -> b) -> b -> Signed a -> b
foldr a -> b -> b
f b
z Signed a
s = a -> b -> b
f (Signed a -> a
forall a. Signed a -> a
unSigned Signed a
s) b
z

instance Traversable Signed where
    traverse :: (a -> f b) -> Signed a -> f (Signed b)
traverse a -> f b
f (Positive a
x) = b -> Signed b
forall a. a -> Signed a
Positive (b -> Signed b) -> f b -> f (Signed b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
x
    traverse a -> f b
f (Negative a
x) = b -> Signed b
forall a. a -> Signed a
Negative (b -> Signed b) -> f b -> f (Signed b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
x

(^~) :: Signed a -> Signed a
^~ :: Signed a -> Signed a
(^~) (Positive a
x) = a -> Signed a
forall a. a -> Signed a
Negative a
x
(^~) (Negative a
x) = a -> Signed a
forall a. a -> Signed a
Positive a
x

isPositive :: Signed a -> Bool
isPositive :: Signed a -> Bool
isPositive (Positive a
_) = Bool
True
isPositive (Negative a
_) = Bool
False

type Element = Signed Generator

element :: Int -> Element
element :: Int -> Element
element = Generator -> Element
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Generator -> Element) -> (Int -> Generator) -> Int -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Generator
generator

getGenerator :: Element -> Generator
getGenerator :: Element -> Generator
getGenerator = Element -> Generator
forall a. Signed a -> a
unSigned

type EWord = [Element]