{-# LANGUAGE
    DataKinds
  , DeriveAnyClass
  , DeriveDataTypeable
  , DeriveGeneric
  , DerivingVia
  , GeneralizedNewtypeDeriving
  , KindSignatures
  , ScopedTypeVariables
  , StandaloneDeriving
  , TypeApplications
  , TypeOperators
  , UndecidableInstances
#-}

{-|
Module: Data.Group

A 'Group' is a 'Monoid' for which the monoid operation can be undone.

That is, \( G \) is a group if each \( g \in G \) has an inverse element \( g^{ -1 } \) such that

\[ g^{ -1 } < \! > g = \text{mempty} = g < \! > g^{ -1 } \]

Such inverses are necessarily unique.


In Haskell, groups are mostly useful to describe objects possessing certain symmetries (such as translation or rotation).

To automatically derive 'Group' instances, you can:

- Use @DerivingVia@ to coerce an existing instance:

> > newtype Seconds   = Seconds { getSeconds :: Double }
> > newtype TimeDelta = TimeDelta { timeDeltaInSeconds :: Seconds }
> >   deriving ( Semigroup, Monoid, Group )
> >     via Sum Double

- Use 'Generic' and 'Generic.Data.Generically':

> > data MyRecord
> >   = MyRecord
> >   { field1 :: Sum Double
> >   , field2 :: Product Double
> >   , field3 :: Ap [] ( Sum Int, Sum Int )
> >   }
> >   deriving Generic
> >   deriving ( Semigroup, Monoid, Group )
> >     via Generically MyRecord
-}


module Data.Group
  ( Group(..)
  , Isom(..)
  )
  where

-- base

import Control.Monad.ST
  ( ST )
import Data.Data
  ( Data )
import Data.Functor.Const
  ( Const(..) )
import Data.Functor.Contravariant
  ( Op(..) )
import Data.Functor.Identity
  ( Identity(..) )
import Data.Monoid
  ( Ap(..), Sum(..), Product(..) )
import Data.Ord
  ( Down(..) )
import Data.Semigroup
  ( Semigroup(..), Dual(..) )
import Data.Proxy
  ( Proxy(..) )
import GHC.Generics
  ( Generic, Generic1
  , U1(..), Rec1(..), M1(..), K1(..), Par1(..), (:*:)(..)
  , V1, (:+:)
  )
import qualified GHC.Generics as Generic
  ( Generic(..) )
import GHC.TypeLits
  ( TypeError, ErrorMessage(Text) )

-- deepseq

import Control.DeepSeq
  ( NFData )

-- generic-data

import Generic.Data
  ( Generically(..) )

-----------------------------------------------------------------------


-- | A 'Group' is a 'Monoid' with inverses:

--

-- * @ inverse g <> g = g <> inverse g = mempty @

--

-- * @ inverse (g <> h) = inverse h <> inverse g @

class Monoid g => Group g where
  {-# MINIMAL inverse | gtimes #-}
  -- | Group inversion anti-homomorphism.

  inverse :: g -> g
  inverse = Int -> g -> g
forall g n. (Group g, Integral n) => n -> g -> g
gtimes ( (-Int
1) :: Int )

  -- | Take the @n@-th power of an element.

  gtimes :: Integral n => n -> g -> g
  gtimes n
n = case n -> n -> Ordering
forall a. Ord a => a -> a -> Ordering
compare n
n n
0 of
    Ordering
EQ -> g -> g -> g
forall a b. a -> b -> a
const g
forall a. Monoid a => a
mempty
    Ordering
GT -> n -> g -> g
forall a b. (Semigroup a, Integral b) => b -> a -> a
stimes n
n
    Ordering
LT -> n -> g -> g
forall a b. (Semigroup a, Integral b) => b -> a -> a
stimes ( n -> n
forall a. Num a => a -> a
negate n
n ) (g -> g) -> (g -> g) -> g -> g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. g -> g
forall g. Group g => g -> g
inverse

-----------------------------------------------------------------------

-- Instances.


-- | Trivial group.

instance Group () where
  inverse :: () -> ()
inverse  ()
_ = ()
  gtimes :: n -> () -> ()
gtimes n
_ ()
_ = ()

-- | Additive groups (via 'Num').

instance Num a => Group ( Sum a ) where
  inverse :: Sum a -> Sum a
inverse  ( Sum a
a ) = a -> Sum a
forall a. a -> Sum a
Sum ( a -> a
forall a. Num a => a -> a
negate a
a )
  gtimes :: n -> Sum a -> Sum a
gtimes n
n ( Sum a
a ) = a -> Sum a
forall a. a -> Sum a
Sum ( n -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral n
n a -> a -> a
forall a. Num a => a -> a -> a
* a
a )

-- | Multiplicative group (via 'Num').

instance Fractional a => Group ( Product a ) where
  inverse :: Product a -> Product a
inverse  ( Product a
a ) = a -> Product a
forall a. a -> Product a
Product ( a -> a
forall a. Fractional a => a -> a
recip a
a )
  gtimes :: n -> Product a -> Product a
gtimes n
n ( Product a
a ) = a -> Product a
forall a. a -> Product a
Product ( a
a a -> Integer -> a
forall a b. (Fractional a, Integral b) => a -> b -> a
^^ n -> Integer
forall a. Integral a => a -> Integer
toInteger n
n )

-- | Opposite group.

instance Group a => Group ( Dual a ) where
  inverse :: Dual a -> Dual a
inverse  ( Dual a
a ) = a -> Dual a
forall a. a -> Dual a
Dual ( a -> a
forall g. Group g => g -> g
inverse a
a )
  gtimes :: n -> Dual a -> Dual a
gtimes n
n ( Dual a
a ) = a -> Dual a
forall a. a -> Dual a
Dual ( n -> a -> a
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n a
a )

-- | Lifting group operations through an applicative functor.

instance ( Group a, Applicative f ) => Group ( Ap f a ) where
  inverse :: Ap f a -> Ap f a
inverse  = (a -> a) -> Ap f a -> Ap f a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall g. Group g => g -> g
inverse
  gtimes :: n -> Ap f a -> Ap f a
gtimes n
n = (a -> a) -> Ap f a -> Ap f a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ( n -> a -> a
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n )

deriving via Ap ((->) r) a instance Group a => Group ( r  ->  a )
deriving via Ap IO       a instance Group a => Group ( IO     a )
deriving via Ap (ST s)   a instance Group a => Group ( ST s   a )

deriving newtype instance Group a => Group ( Down     a )
deriving newtype instance Group a => Group ( Identity a )
deriving newtype instance Group a => Group ( Const a b )
deriving newtype instance Group a => Group ( Op    a b )

instance Group ( Proxy p ) where
  inverse :: Proxy p -> Proxy p
inverse  Proxy p
_ = Proxy p
forall k (t :: k). Proxy t
Proxy
  gtimes :: n -> Proxy p -> Proxy p
gtimes n
_ Proxy p
_ = Proxy p
forall k (t :: k). Proxy t
Proxy

instance ( Group g1, Group g2 )
      => Group ( g1, g2 ) where
  inverse :: (g1, g2) -> (g1, g2)
inverse  ( g1
g1, g2
g2 ) =
    ( g1 -> g1
forall g. Group g => g -> g
inverse g1
g1, g2 -> g2
forall g. Group g => g -> g
inverse g2
g2 )
  gtimes :: n -> (g1, g2) -> (g1, g2)
gtimes n
n ( g1
g1, g2
g2 ) =
    ( n -> g1 -> g1
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g1
g1, n -> g2 -> g2
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g2
g2 )

instance ( Group g1, Group g2, Group g3 )
      => Group ( g1, g2, g3 ) where
  inverse :: (g1, g2, g3) -> (g1, g2, g3)
inverse  ( g1
g1, g2
g2, g3
g3 ) =
    ( g1 -> g1
forall g. Group g => g -> g
inverse g1
g1, g2 -> g2
forall g. Group g => g -> g
inverse g2
g2, g3 -> g3
forall g. Group g => g -> g
inverse g3
g3 )
  gtimes :: n -> (g1, g2, g3) -> (g1, g2, g3)
gtimes n
n ( g1
g1, g2
g2, g3
g3 ) =
    ( n -> g1 -> g1
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g1
g1, n -> g2 -> g2
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g2
g2, n -> g3 -> g3
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g3
g3 )

instance ( Group g1, Group g2, Group g3, Group g4 )
      => Group ( g1, g2, g3, g4 ) where
  inverse :: (g1, g2, g3, g4) -> (g1, g2, g3, g4)
inverse  ( g1
g1, g2
g2, g3
g3, g4
g4 ) =
    ( g1 -> g1
forall g. Group g => g -> g
inverse g1
g1, g2 -> g2
forall g. Group g => g -> g
inverse g2
g2, g3 -> g3
forall g. Group g => g -> g
inverse g3
g3, g4 -> g4
forall g. Group g => g -> g
inverse g4
g4 )
  gtimes :: n -> (g1, g2, g3, g4) -> (g1, g2, g3, g4)
gtimes n
n ( g1
g1, g2
g2, g3
g3, g4
g4 ) =
    ( n -> g1 -> g1
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g1
g1, n -> g2 -> g2
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g2
g2, n -> g3 -> g3
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g3
g3, n -> g4 -> g4
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g4
g4 )

instance ( Group g1, Group g2, Group g3, Group g4, Group g5 )
      => Group ( g1, g2, g3, g4, g5 ) where
  inverse :: (g1, g2, g3, g4, g5) -> (g1, g2, g3, g4, g5)
inverse  ( g1
g1, g2
g2, g3
g3, g4
g4, g5
g5 ) =
    ( g1 -> g1
forall g. Group g => g -> g
inverse g1
g1, g2 -> g2
forall g. Group g => g -> g
inverse g2
g2, g3 -> g3
forall g. Group g => g -> g
inverse g3
g3, g4 -> g4
forall g. Group g => g -> g
inverse g4
g4, g5 -> g5
forall g. Group g => g -> g
inverse g5
g5 )
  gtimes :: n -> (g1, g2, g3, g4, g5) -> (g1, g2, g3, g4, g5)
gtimes n
n ( g1
g1, g2
g2, g3
g3, g4
g4, g5
g5 ) =
    ( n -> g1 -> g1
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g1
g1, n -> g2 -> g2
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g2
g2, n -> g3 -> g3
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g3
g3, n -> g4 -> g4
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g4
g4, n -> g5 -> g5
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g5
g5 )

infix 7 :|:
-- | Data type to keep track of a pair of inverse elements.

data Isom a = (:|:) { Isom a -> a
to :: a, Isom a -> Dual a
from :: Dual a }
  deriving stock    ( Int -> Isom a -> ShowS
[Isom a] -> ShowS
Isom a -> String
(Int -> Isom a -> ShowS)
-> (Isom a -> String) -> ([Isom a] -> ShowS) -> Show (Isom a)
forall a. Show a => Int -> Isom a -> ShowS
forall a. Show a => [Isom a] -> ShowS
forall a. Show a => Isom a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Isom a] -> ShowS
$cshowList :: forall a. Show a => [Isom a] -> ShowS
show :: Isom a -> String
$cshow :: forall a. Show a => Isom a -> String
showsPrec :: Int -> Isom a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Isom a -> ShowS
Show, ReadPrec [Isom a]
ReadPrec (Isom a)
Int -> ReadS (Isom a)
ReadS [Isom a]
(Int -> ReadS (Isom a))
-> ReadS [Isom a]
-> ReadPrec (Isom a)
-> ReadPrec [Isom a]
-> Read (Isom a)
forall a. Read a => ReadPrec [Isom a]
forall a. Read a => ReadPrec (Isom a)
forall a. Read a => Int -> ReadS (Isom a)
forall a. Read a => ReadS [Isom a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Isom a]
$creadListPrec :: forall a. Read a => ReadPrec [Isom a]
readPrec :: ReadPrec (Isom a)
$creadPrec :: forall a. Read a => ReadPrec (Isom a)
readList :: ReadS [Isom a]
$creadList :: forall a. Read a => ReadS [Isom a]
readsPrec :: Int -> ReadS (Isom a)
$creadsPrec :: forall a. Read a => Int -> ReadS (Isom a)
Read, Typeable (Isom a)
DataType
Constr
Typeable (Isom a)
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Isom a -> c (Isom a))
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (Isom a))
-> (Isom a -> Constr)
-> (Isom a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (Isom a)))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Isom a)))
-> ((forall b. Data b => b -> b) -> Isom a -> Isom a)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Isom a -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Isom a -> r)
-> (forall u. (forall d. Data d => d -> u) -> Isom a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Isom a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Isom a -> m (Isom a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Isom a -> m (Isom a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Isom a -> m (Isom a))
-> Data (Isom a)
Isom a -> DataType
Isom a -> Constr
(forall d. Data d => c (t d)) -> Maybe (c (Isom a))
(forall b. Data b => b -> b) -> Isom a -> Isom a
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Isom a -> c (Isom a)
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Isom a)
forall a. Data a => Typeable (Isom a)
forall a. Data a => Isom a -> DataType
forall a. Data a => Isom a -> Constr
forall a.
Data a =>
(forall b. Data b => b -> b) -> Isom a -> Isom a
forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Isom a -> u
forall a u. Data a => (forall d. Data d => d -> u) -> Isom a -> [u]
forall a r r'.
Data a =>
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Isom a -> r
forall a r r'.
Data a =>
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Isom a -> r
forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Isom a)
forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Isom a -> c (Isom a)
forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Isom a))
forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Isom a))
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Isom a -> u
forall u. (forall d. Data d => d -> u) -> Isom a -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Isom a -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Isom a -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Isom a)
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Isom a -> c (Isom a)
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Isom a))
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Isom a))
$c:|: :: Constr
$tIsom :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
$cgmapMo :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
gmapMp :: (forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
$cgmapMp :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
gmapM :: (forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
$cgmapM :: forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Isom a -> m (Isom a)
gmapQi :: Int -> (forall d. Data d => d -> u) -> Isom a -> u
$cgmapQi :: forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Isom a -> u
gmapQ :: (forall d. Data d => d -> u) -> Isom a -> [u]
$cgmapQ :: forall a u. Data a => (forall d. Data d => d -> u) -> Isom a -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Isom a -> r
$cgmapQr :: forall a r r'.
Data a =>
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Isom a -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Isom a -> r
$cgmapQl :: forall a r r'.
Data a =>
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Isom a -> r
gmapT :: (forall b. Data b => b -> b) -> Isom a -> Isom a
$cgmapT :: forall a.
Data a =>
(forall b. Data b => b -> b) -> Isom a -> Isom a
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Isom a))
$cdataCast2 :: forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Isom a))
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c (Isom a))
$cdataCast1 :: forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Isom a))
dataTypeOf :: Isom a -> DataType
$cdataTypeOf :: forall a. Data a => Isom a -> DataType
toConstr :: Isom a -> Constr
$ctoConstr :: forall a. Data a => Isom a -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Isom a)
$cgunfold :: forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Isom a)
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Isom a -> c (Isom a)
$cgfoldl :: forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Isom a -> c (Isom a)
$cp1Data :: forall a. Data a => Typeable (Isom a)
Data, (forall x. Isom a -> Rep (Isom a) x)
-> (forall x. Rep (Isom a) x -> Isom a) -> Generic (Isom a)
forall x. Rep (Isom a) x -> Isom a
forall x. Isom a -> Rep (Isom a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Isom a) x -> Isom a
forall a x. Isom a -> Rep (Isom a) x
$cto :: forall a x. Rep (Isom a) x -> Isom a
$cfrom :: forall a x. Isom a -> Rep (Isom a) x
Generic, (forall a. Isom a -> Rep1 Isom a)
-> (forall a. Rep1 Isom a -> Isom a) -> Generic1 Isom
forall a. Rep1 Isom a -> Isom a
forall a. Isom a -> Rep1 Isom a
forall k (f :: k -> *).
(forall (a :: k). f a -> Rep1 f a)
-> (forall (a :: k). Rep1 f a -> f a) -> Generic1 f
$cto1 :: forall a. Rep1 Isom a -> Isom a
$cfrom1 :: forall a. Isom a -> Rep1 Isom a
Generic1 )
  deriving anyclass Isom a -> ()
(Isom a -> ()) -> NFData (Isom a)
forall a. NFData a => Isom a -> ()
forall a. (a -> ()) -> NFData a
rnf :: Isom a -> ()
$crnf :: forall a. NFData a => Isom a -> ()
NFData
instance Semigroup a => Semigroup ( Isom a ) where
  ( a
p1 :|: Dual a
q1 ) <> :: Isom a -> Isom a -> Isom a
<> ( a
p2 :|: Dual a
q2 ) = ( a
p1 a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
p2 ) a -> Dual a -> Isom a
forall a. a -> Dual a -> Isom a
:|: ( Dual a
q1 Dual a -> Dual a -> Dual a
forall a. Semigroup a => a -> a -> a
<> Dual a
q2 )
instance Monoid a => Monoid ( Isom a ) where
  mempty :: Isom a
mempty = a
forall a. Monoid a => a
mempty a -> Dual a -> Isom a
forall a. a -> Dual a -> Isom a
:|: Dual a
forall a. Monoid a => a
mempty
instance Monoid a => Group ( Isom a ) where
  inverse :: Isom a -> Isom a
inverse ( a
p :|: Dual a
q ) = Dual a -> a
forall a. Dual a -> a
getDual Dual a
q a -> Dual a -> Isom a
forall a. a -> Dual a -> Isom a
:|: a -> Dual a
forall a. a -> Dual a
Dual a
p

-- Generics.


instance Group ( U1 p ) where
  inverse :: U1 p -> U1 p
inverse  U1 p
_ = U1 p
forall k (p :: k). U1 p
U1
  gtimes :: n -> U1 p -> U1 p
gtimes n
_ U1 p
_ = U1 p
forall k (p :: k). U1 p
U1

deriving newtype instance Group ( f p ) => Group ( Rec1 f p )
deriving newtype instance Group ( f p ) => Group ( M1 i c f p )
deriving newtype instance Group g       => Group ( K1 i g p )
deriving newtype instance Group g       => Group ( Par1 g )

instance ( Group ( f1 p ), Group ( f2 p ) ) => Group ( (f1 :*: f2) p ) where
  inverse :: (:*:) f1 f2 p -> (:*:) f1 f2 p
inverse  ( f1 p
g1 :*: f2 p
g2 ) = ( f1 p -> f1 p
forall g. Group g => g -> g
inverse  f1 p
g1 f1 p -> f2 p -> (:*:) f1 f2 p
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: f2 p -> f2 p
forall g. Group g => g -> g
inverse  f2 p
g2 )
  gtimes :: n -> (:*:) f1 f2 p -> (:*:) f1 f2 p
gtimes n
n ( f1 p
g1 :*: f2 p
g2 ) = ( n -> f1 p -> f1 p
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n f1 p
g1 f1 p -> f2 p -> (:*:) f1 f2 p
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: n -> f2 p -> f2 p
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n f2 p
g2 )

instance
  ( Generic g
  , Monoid  ( Generic.Rep g () )
  , GGroup  ( Generic.Rep g )
  )
  => Group ( Generically g ) where
  inverse :: Generically g -> Generically g
inverse  = g -> Generically g
forall a. a -> Generically a
Generically (g -> Generically g)
-> (Generically g -> g) -> Generically g -> Generically g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rep g Any -> g
forall a x. Generic a => Rep a x -> a
Generic.to (Rep g Any -> g)
-> (Generically g -> Rep g Any) -> Generically g -> g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rep g Any -> Rep g Any
forall (f :: * -> *) p. GGroup f => f p -> f p
ginverse  (Rep g Any -> Rep g Any)
-> (Generically g -> Rep g Any) -> Generically g -> Rep g Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. g -> Rep g Any
forall a x. Generic a => a -> Rep a x
Generic.from (g -> Rep g Any)
-> (Generically g -> g) -> Generically g -> Rep g Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Generically g -> g
forall a. Generically a -> a
unGenerically
  gtimes :: n -> Generically g -> Generically g
gtimes n
n = g -> Generically g
forall a. a -> Generically a
Generically (g -> Generically g)
-> (Generically g -> g) -> Generically g -> Generically g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rep g Any -> g
forall a x. Generic a => Rep a x -> a
Generic.to (Rep g Any -> g)
-> (Generically g -> Rep g Any) -> Generically g -> g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> Rep g Any -> Rep g Any
forall (f :: * -> *) n p. (GGroup f, Integral n) => n -> f p -> f p
ggtimes n
n (Rep g Any -> Rep g Any)
-> (Generically g -> Rep g Any) -> Generically g -> Rep g Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. g -> Rep g Any
forall a x. Generic a => a -> Rep a x
Generic.from (g -> Rep g Any)
-> (Generically g -> g) -> Generically g -> Rep g Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Generically g -> g
forall a. Generically a -> a
unGenerically

-- | Type class used for deriving 'Group' instances generically.

class GGroup f where
  ginverse :: f p -> f p
  ggtimes  :: Integral n => n -> f p -> f p

instance GGroup U1 where
  ginverse :: U1 p -> U1 p
ginverse  U1 p
_ = U1 p
forall k (p :: k). U1 p
U1
  ggtimes :: n -> U1 p -> U1 p
ggtimes n
_ U1 p
_ = U1 p
forall k (p :: k). U1 p
U1

deriving newtype instance GGroup f => GGroup ( Rec1 f )
deriving newtype instance GGroup f => GGroup ( M1 i c f )

instance Group g => GGroup ( K1 i g ) where
  ginverse :: K1 i g p -> K1 i g p
ginverse  ( K1 g
g ) = g -> K1 i g p
forall k i c (p :: k). c -> K1 i c p
K1 ( g -> g
forall g. Group g => g -> g
inverse  g
g )
  ggtimes :: n -> K1 i g p -> K1 i g p
ggtimes n
n ( K1 g
g ) = g -> K1 i g p
forall k i c (p :: k). c -> K1 i c p
K1 ( n -> g -> g
forall g n. (Group g, Integral n) => n -> g -> g
gtimes n
n g
g )

instance ( GGroup f1, GGroup f2 ) => GGroup ( f1 :*: f2 ) where
  ginverse :: (:*:) f1 f2 p -> (:*:) f1 f2 p
ginverse  ( f1 p
g1 :*: f2 p
g2 ) = ( f1 p -> f1 p
forall (f :: * -> *) p. GGroup f => f p -> f p
ginverse  f1 p
g1 f1 p -> f2 p -> (:*:) f1 f2 p
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: f2 p -> f2 p
forall (f :: * -> *) p. GGroup f => f p -> f p
ginverse  f2 p
g2 )
  ggtimes :: n -> (:*:) f1 f2 p -> (:*:) f1 f2 p
ggtimes n
n ( f1 p
g1 :*: f2 p
g2 ) = ( n -> f1 p -> f1 p
forall (f :: * -> *) n p. (GGroup f, Integral n) => n -> f p -> f p
ggtimes n
n f1 p
g1 f1 p -> f2 p -> (:*:) f1 f2 p
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: n -> f2 p -> f2 p
forall (f :: * -> *) n p. (GGroup f, Integral n) => n -> f p -> f p
ggtimes n
n f2 p
g2 )

instance
  TypeError ( 'Text "No 'Group' instance for empty generic representation." )
  => GGroup V1 where
  ginverse :: V1 p -> V1 p
ginverse  V1 p
_ = String -> V1 p
forall a. HasCallStack => String -> a
error String
"unreachable"
  ggtimes :: n -> V1 p -> V1 p
ggtimes n
_ V1 p
_ = String -> V1 p
forall a. HasCallStack => String -> a
error String
"unreachable"

instance
  TypeError ( 'Text "No 'Group' instance for generic sum type." )
  => GGroup ( f1 :+: f2 ) where
  ginverse :: (:+:) f1 f2 p -> (:+:) f1 f2 p
ginverse  (:+:) f1 f2 p
_ = String -> (:+:) f1 f2 p
forall a. HasCallStack => String -> a
error String
"unreachable"
  ggtimes :: n -> (:+:) f1 f2 p -> (:+:) f1 f2 p
ggtimes n
_ (:+:) f1 f2 p
_ = String -> (:+:) f1 f2 p
forall a. HasCallStack => String -> a
error String
"unreachable"