module Group
( Group(..)
) where
import Protolude
import Control.Monad.Random (MonadRandom, Random, getRandom)
import Test.Tasty.QuickCheck (Arbitrary)
import Text.PrettyPrint.Leijen.Text (Pretty)
class (Arbitrary g, Eq g, Generic g,
Monoid g, Pretty g, Random g, Show g) => Group g where
{-# MINIMAL add, dbl, def, gen, id, inv, order #-}
add :: g -> g -> g
dbl :: g -> g
def :: g -> Bool
gen :: g
id :: g
inv :: g -> g
mul' :: g -> Integer -> g
mul' p n
| n < 0 = inv (mul' p (-n))
| n == 0 = id
| n == 1 = p
| even n = p'
| otherwise = add p p'
where
p' = mul' (dbl p) (div n 2)
{-# INLINABLE mul' #-}
order :: g -> Integer
rnd :: MonadRandom m => m g
rnd = getRandom
{-# INLINABLE rnd #-}