module Group.Field
( module Group
, module Group.Field
) where
import Protolude
import Control.Monad.Random (Random(..))
import GaloisField (GaloisField(..))
import Test.Tasty.QuickCheck (Arbitrary(..))
import Text.PrettyPrint.Leijen.Text (Pretty(..))
import Curve (PrimeField')
import Group (Group(..))
class (GaloisField q, PrimeField' r) => FGroup r q where
{-# MINIMAL g_, h_, q_, r_ #-}
g_ :: Element r q
h_ :: Element r q -> Integer
q_ :: Element r q -> Integer
r_ :: Element r q -> Integer
newtype Element r q = F q
deriving (Eq, Functor, Generic, NFData, Read, Show)
instance FGroup r q => Group (Element r q) where
add = (<>)
{-# INLINABLE add #-}
dbl = join (<>)
{-# INLINABLE dbl #-}
def (F x) = x /= 0
{-# INLINABLE def #-}
gen = g_
{-# INLINABLE gen #-}
id = mempty
{-# INLINABLE id #-}
inv = (<$>) recip
{-# INLINABLE inv #-}
mul' = (. flip pow) . flip (<$>)
{-# INLINABLE mul' #-}
order = r_
{-# INLINABLE order #-}
instance FGroup r q => Monoid (Element r q) where
mempty = F 1
{-# INLINABLE mempty #-}
instance FGroup r q => Semigroup (Element r q) where
F x <> F y = F (x * y)
{-# INLINABLE (<>) #-}
instance FGroup r q => Arbitrary (Element r q) where
arbitrary = mul' gen <$> arbitrary
{-# INLINABLE arbitrary #-}
instance FGroup r q => Pretty (Element r q) where
pretty (F x) = pretty x
instance FGroup r q => Random (Element r q) where
random = first (mul' gen) . random
{-# INLINABLE random #-}
randomR = panic "not implemented."