module GP2GAP (
    gapFormat,
  ) where

import GroupPresentation

import Data.List (intercalate)

type GAPformat = String

gapFormat :: MonadFail m => GroupPresentation -> m GAPformat
gapFormat :: GroupPresentation -> m GAPformat
gapFormat GroupPresentation
gp = do
    GAPformat
gens <- GroupPresentation -> m GAPformat
forall (m :: * -> *).
MonadFail m =>
GroupPresentation -> m GAPformat
gens2str GroupPresentation
gp
    GAPformat
rels <- GroupPresentation -> m GAPformat
forall (m :: * -> *).
MonadFail m =>
GroupPresentation -> m GAPformat
rels2str GroupPresentation
gp
    GAPformat -> m GAPformat
forall (m :: * -> *) a. Monad m => a -> m a
return (GAPformat -> m GAPformat) -> GAPformat -> m GAPformat
forall a b. (a -> b) -> a -> b
$
        GAPformat
"local f, g;\n\
        \f := FreeGroup( " GAPformat -> GAPformat -> GAPformat
forall a. [a] -> [a] -> [a]
++ GAPformat
gens GAPformat -> GAPformat -> GAPformat
forall a. [a] -> [a] -> [a]
++ GAPformat
" );\n\
        \g := f / [ " GAPformat -> GAPformat -> GAPformat
forall a. [a] -> [a] -> [a]
++ GAPformat
rels GAPformat -> GAPformat -> GAPformat
forall a. [a] -> [a] -> [a]
++ GAPformat
" ];\n\
        \return g;\n"

gens2str :: MonadFail m => GroupPresentation -> m String
gens2str :: GroupPresentation -> m GAPformat
gens2str GroupPresentation
gp = GAPformat -> m GAPformat
forall (m :: * -> *) a. Monad m => a -> m a
return (GAPformat -> m GAPformat) -> GAPformat -> m GAPformat
forall a b. (a -> b) -> a -> b
$ GAPformat -> [GAPformat] -> GAPformat
forall a. [a] -> [[a]] -> [a]
intercalate GAPformat
", " ([GAPformat] -> GAPformat) -> [GAPformat] -> GAPformat
forall a b. (a -> b) -> a -> b
$ Set GAPformat -> [GAPformat]
forall c v. Listable c v => c -> [v]
toList (Set GAPformat -> [GAPformat]) -> Set GAPformat -> [GAPformat]
forall a b. (a -> b) -> a -> b
$ GroupPresentation
gpGroupPresentation
-> Getting (Set GAPformat) GroupPresentation (Set GAPformat)
-> Set GAPformat
forall s a. s -> Getting a s a -> a
^.Getting (Set GAPformat) GroupPresentation (Set GAPformat)
GPGetter (Set GAPformat)
strGenerators

rels2str :: MonadFail m => GroupPresentation -> m String
rels2str :: GroupPresentation -> m GAPformat
rels2str GroupPresentation
gp = do
    let gd :: GeneratorsDescr
gd = GroupPresentation
gpGroupPresentation
-> Getting GeneratorsDescr GroupPresentation GeneratorsDescr
-> GeneratorsDescr
forall s a. s -> Getting a s a -> a
^.Getting GeneratorsDescr GroupPresentation GeneratorsDescr
Lens' GroupPresentation GeneratorsDescr
generatorsDescr
    [GAPformat]
rels <- (Relation -> m GAPformat) -> [Relation] -> m [GAPformat]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (GeneratorsDescr -> Relation -> m GAPformat
forall (m :: * -> *).
MonadFail m =>
GeneratorsDescr -> Relation -> m GAPformat
rel2str GeneratorsDescr
gd) (Relations -> [Relation]
forall c v. Listable c v => c -> [v]
toList (Relations -> [Relation]) -> Relations -> [Relation]
forall a b. (a -> b) -> a -> b
$ GroupPresentation
gpGroupPresentation
-> Getting Relations GroupPresentation Relations -> Relations
forall s a. s -> Getting a s a -> a
^.Getting Relations GroupPresentation Relations
Lens' GroupPresentation Relations
relations)
    GAPformat -> m GAPformat
forall (m :: * -> *) a. Monad m => a -> m a
return (GAPformat -> m GAPformat) -> GAPformat -> m GAPformat
forall a b. (a -> b) -> a -> b
$ GAPformat -> [GAPformat] -> GAPformat
forall a. [a] -> [[a]] -> [a]
intercalate GAPformat
", " [GAPformat]
rels

rel2str :: MonadFail m => GeneratorsDescr -> Relation -> m String
rel2str :: GeneratorsDescr -> Relation -> m GAPformat
rel2str GeneratorsDescr
gd (Pair (EWord
ew1, EWord
ew2)) = do
    let ew :: EWord
ew = EWord
ew1 EWord -> EWord -> EWord
forall a. [a] -> [a] -> [a]
++ EWord -> EWord
forall a. [a] -> [a]
reverse (Signed Generator -> Signed Generator
forall a. Signed a -> Signed a
(^~) (Signed Generator -> Signed Generator) -> EWord -> EWord
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> EWord
ew2)
    [GAPformat]
es <- (Signed Generator -> m GAPformat) -> EWord -> m [GAPformat]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (GeneratorsDescr -> Signed Generator -> m GAPformat
forall (m :: * -> *).
MonadFail m =>
GeneratorsDescr -> Signed Generator -> m GAPformat
elem2str GeneratorsDescr
gd) EWord
ew
    GAPformat -> m GAPformat
forall (m :: * -> *) a. Monad m => a -> m a
return (GAPformat -> m GAPformat) -> GAPformat -> m GAPformat
forall a b. (a -> b) -> a -> b
$ GAPformat -> [GAPformat] -> GAPformat
forall a. [a] -> [[a]] -> [a]
intercalate GAPformat
" * " [GAPformat]
es

elem2str :: MonadFail m => GeneratorsDescr -> Element -> m String
elem2str :: GeneratorsDescr -> Signed Generator -> m GAPformat
elem2str GeneratorsDescr
gd (Positive Generator
g) = GeneratorsDescr
gd GeneratorsDescr -> Generator -> m GAPformat
forall c k v (m :: * -> *).
(Indexable c k v, MonadFail m) =>
c -> k -> m v
!? Generator
g
elem2str GeneratorsDescr
gd (Negative Generator
g) = (GAPformat -> GAPformat -> GAPformat
forall a. [a] -> [a] -> [a]
++ GAPformat
"^(-1)") (GAPformat -> GAPformat) -> m GAPformat -> m GAPformat
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (GeneratorsDescr
gd GeneratorsDescr -> Generator -> m GAPformat
forall c k v (m :: * -> *).
(Indexable c k v, MonadFail m) =>
c -> k -> m v
!? Generator
g)