{-# 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 a = go 1 a where
go !n g
| g == mempty = n
| otherwise = go (succ n) (g <> a)
{-# inline finiteOrder #-}
safeClassify :: (Eq a, Cyclic a, FiniteGroup a) => (a -> Bool) -> [a]
safeClassify = 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)