```-- |
-- Module:      Math.NumberTheory.Moduli.Class
-- Copyright:   (c) 2017 Andrew Lelechenko
-- Licence:     MIT
-- Maintainer:  Andrew Lelechenko <andrew.lelechenko@gmail.com>
--
-- Safe modular arithmetic with modulo on type level.
--

{-# LANGUAGE DataKinds                  #-}
{-# LANGUAGE KindSignatures             #-}
{-# LANGUAGE RankNTypes                 #-}
{-# LANGUAGE ScopedTypeVariables        #-}

module Math.NumberTheory.Moduli.Class
( -- * Known modulo
Mod
, getVal
, getNatVal
, getMod
, getNatMod
, invertMod
, powMod
, (^%)
-- * Multiplicative group
, MultMod
, multElement
, isMultElement
, invertGroup
-- * Unknown modulo
, SomeMod(..)
, modulo
, invertSomeMod
, powSomeMod
-- * Re-exported from GHC.TypeNats.Compat
, KnownNat
) where

import Data.Mod
import GHC.Natural
import GHC.TypeNats (KnownNat, natVal)

import Math.NumberTheory.Moduli.Multiplicative
import Math.NumberTheory.Moduli.SomeMod

-- | Linking type and value levels: extract modulo @m@ as a value.
getMod :: KnownNat m => Mod m -> Integer
getMod :: forall (m :: Nat). KnownNat m => Mod m -> Integer
getMod = forall a. Integral a => a -> Integer
toInteger forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (n :: Nat) (proxy :: Nat -> *). KnownNat n => proxy n -> Nat
natVal
{-# INLINE getMod #-}

-- | Linking type and value levels: extract modulo @m@ as a value.
getNatMod :: KnownNat m => Mod m -> Natural
getNatMod :: forall (m :: Nat). KnownNat m => Mod m -> Nat
getNatMod = forall (n :: Nat) (proxy :: Nat -> *). KnownNat n => proxy n -> Nat
natVal
{-# INLINE getNatMod #-}

-- | The canonical representative of the residue class, always between 0 and m-1 inclusively.
getVal :: Mod m -> Integer
getVal :: forall (m :: Nat). Mod m -> Integer
getVal = forall a. Integral a => a -> Integer
toInteger forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: Nat). Mod m -> Nat
unMod
{-# INLINE getVal #-}

-- | The canonical representative of the residue class, always between 0 and m-1 inclusively.
getNatVal :: Mod m -> Natural
getNatVal :: forall (m :: Nat). Mod m -> Nat
getNatVal = forall (m :: Nat). Mod m -> Nat
unMod
{-# INLINE getNatVal #-}

-- | Synonym of '(^%)'.
powMod :: (KnownNat m, Integral a) => Mod m -> a -> Mod m
powMod :: forall (m :: Nat) a.
(KnownNat m, Integral a) =>
Mod m -> a -> Mod m
powMod = forall (m :: Nat) a.
(KnownNat m, Integral a) =>
Mod m -> a -> Mod m
(^%)
{-# INLINE powMod #-}
```