{-# language CPP #-}
{-# language FlexibleInstances #-}
{-# language BangPatterns #-}
{-# language Safe #-}
module Data.Group.Finite
(
FiniteGroup
, finiteOrder
, safeClassify
, FiniteAbelianGroup
) where
import Data.Functor.Const
import Data.Functor.Identity
import Data.Group
import Data.Monoid
import Data.Proxy
import Data.Group.Cyclic
import Numeric.Natural (Natural)
class (Group g, Bounded g) => FiniteGroup g where
instance FiniteGroup ()
instance FiniteGroup a => FiniteGroup (Dual a)
instance FiniteGroup a => FiniteGroup (Const a b)
instance FiniteGroup a => FiniteGroup (Identity a)
instance FiniteGroup a => FiniteGroup (Proxy a)
instance (FiniteGroup a, FiniteGroup b) => FiniteGroup (a,b)
instance (FiniteGroup a, FiniteGroup b, FiniteGroup c) => FiniteGroup (a,b,c)
instance (FiniteGroup a, FiniteGroup b, FiniteGroup c, FiniteGroup d) => FiniteGroup (a,b,c,d)
instance (FiniteGroup a, FiniteGroup b, FiniteGroup c, FiniteGroup d, FiniteGroup e) => FiniteGroup (a,b,c,d,e)
instance (Bounded a, Num a) => FiniteGroup (Sum a)
finiteOrder :: (Eq g, FiniteGroup g) => g -> Natural
finiteOrder :: g -> Natural
finiteOrder g
a = Natural -> g -> Natural
forall t. Enum t => t -> g -> t
go Natural
1 g
a where
go :: t -> g -> t
go !t
n g
g
| g
g g -> g -> Bool
forall a. Eq a => a -> a -> Bool
== g
forall a. Monoid a => a
mempty = t
n
| Bool
otherwise = t -> g -> t
go (t -> t
forall a. Enum a => a -> a
succ t
n) (g
g g -> g -> g
forall a. Semigroup a => a -> a -> a
<> g
a)
{-# inline finiteOrder #-}
safeClassify :: (Eq a, Cyclic a, FiniteGroup a) => (a -> Bool) -> [a]
safeClassify :: (a -> Bool) -> [a]
safeClassify = (a -> Bool) -> [a]
forall a. (Eq a, Cyclic a) => (a -> Bool) -> [a]
classify
{-# inline safeClassify #-}
class FiniteGroup g => FiniteAbelianGroup g
instance FiniteAbelianGroup ()
instance FiniteAbelianGroup a => FiniteAbelianGroup (Dual a)
instance (Num a, Bounded a) => FiniteAbelianGroup (Sum a)
instance FiniteAbelianGroup a => FiniteAbelianGroup (Const a b)
instance FiniteAbelianGroup a => FiniteAbelianGroup (Identity a)
instance FiniteAbelianGroup a => FiniteAbelianGroup (Proxy a)
instance (FiniteAbelianGroup a, FiniteAbelianGroup b) => FiniteAbelianGroup (a,b)
instance (FiniteAbelianGroup a, FiniteAbelianGroup b, FiniteAbelianGroup c) => FiniteAbelianGroup (a,b,c)
instance (FiniteAbelianGroup a, FiniteAbelianGroup b, FiniteAbelianGroup c, FiniteAbelianGroup d) => FiniteAbelianGroup (a,b,c,d)
instance (FiniteAbelianGroup a, FiniteAbelianGroup b, FiniteAbelianGroup c, FiniteAbelianGroup d, FiniteAbelianGroup e) => FiniteAbelianGroup (a,b,c,d,e)