{-# LANGUAGE DataKinds, DerivingStrategies, FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, PolyKinds #-}
{-# LANGUAGE RankNTypes, ScopedTypeVariables, TypeApplications #-}
{-# LANGUAGE TypeFamilies, UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Algebra.Field.Finite
( FiniteField(..), order,
ViaElements(..)
) where
import Control.Monad.Random (Random (..), uniform)
import Control.Monad.Trans.Random.Strict (runRand)
import Data.Coerce (coerce)
import Data.Proxy (Proxy (Proxy))
import Numeric.Algebra (Field, Natural, char)
import Numeric.Rig.Characteristic (Characteristic)
import Prelude (($))
import qualified Prelude as P
class (Field k, Characteristic k) => FiniteField k where
power :: proxy k -> Natural
elements :: proxy k -> [k]
order :: FiniteField k => proxy k -> Natural
order :: proxy k -> Natural
order proxy k
p = proxy k -> Natural
forall r (proxy :: * -> *). Characteristic r => proxy r -> Natural
char proxy k
p Natural -> Natural -> Natural
forall a b. (Num a, Integral b) => a -> b -> a
P.^ proxy k -> Natural
forall k (proxy :: * -> *). FiniteField k => proxy k -> Natural
power proxy k
p
{-# INLINE order #-}
newtype ViaElements k = ViaElements { ViaElements k -> k
runViaElements :: k }
instance FiniteField k => Random (ViaElements k) where
random :: g -> (ViaElements k, g)
random = Rand g (ViaElements k) -> g -> (ViaElements k, g)
forall g a. Rand g a -> g -> (a, g)
runRand
(Rand g (ViaElements k) -> g -> (ViaElements k, g))
-> Rand g (ViaElements k) -> g -> (ViaElements k, g)
forall a b. (a -> b) -> a -> b
$ [ViaElements k] -> Rand g (ViaElements k)
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, MonadRandom m) =>
t a -> m a
uniform ([ViaElements k] -> Rand g (ViaElements k))
-> [ViaElements k] -> Rand g (ViaElements k)
forall a b. (a -> b) -> a -> b
$ Coercible [k] [ViaElements k] => [k] -> [ViaElements k]
coerce @_ @[ViaElements k]
([k] -> [ViaElements k]) -> [k] -> [ViaElements k]
forall a b. (a -> b) -> a -> b
$ Proxy k -> [k]
forall k (proxy :: * -> *). FiniteField k => proxy k -> [k]
elements (Proxy k
forall k (t :: k). Proxy t
Proxy :: Proxy k)
{-# INLINE random #-}
randomR :: (ViaElements k, ViaElements k) -> g -> (ViaElements k, g)
randomR = [Char] -> (ViaElements k, ViaElements k) -> g -> (ViaElements k, g)
forall a. HasCallStack => [Char] -> a
P.error [Char]
"randomR: general finite fields not supported"
{-# INLINE randomR #-}