{-# LANGUAGE DataKinds, EmptyDataDecls, FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses, NoImplicitPrelude #-} {-# LANGUAGE NoMonomorphismRestriction, PolyKinds, ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell, UndecidableInstances #-} module Algebra.Field.Galois.Internal (ConwayPolynomial(..), Conway, buildInstance, parseLine ) where import Algebra.Field.Finite import Algebra.Prelude.Core hiding (lex, lift) import Algebra.Ring.Polynomial.Univariate (Unipol) import Data.Char (isDigit) import Data.Char (digitToInt) import Data.Reflection import qualified GHC.TypeLits as TL import Language.Haskell.TH import Language.Haskell.TH.Syntax (lift) import Numeric (readInt) import Prelude (lex) -- | Type-class to provide the dictionary for Conway polynomials class ConwayPolynomial (p :: TL.Nat) (n :: TL.Nat) where conwayPolynomial :: proxy p -> proxy n -> Unipol (F p) -- | Empty tag to reify Conway polynomial to type-level data Conway p n -- instance {-# OVERLAPPABLE #-} (KnownNat p, KnownNat n) => ConwayPolynomial p n where -- conwayPolynomial _ _ = undefined instance (ConwayPolynomial p n) => Reifies (Conway p n) (Unipol (F p)) where reflect _ = conwayPolynomial (Proxy :: Proxy p) (Proxy :: Proxy n) parseLine :: String -> [(Integer, Integer, [Integer])] parseLine ('[':xs) = [(p,n,poly) | (f, ',':rest) <- lex xs , (p, "") <- readInt 10 isDigit digitToInt f , (n, ',':ys) <- readInt 10 isDigit digitToInt rest , (poly, _) <- readList ys ] parseLine _ = [] plusOp :: ExpQ -> ExpQ -> ExpQ plusOp e f = infixApp e [| (+) |] f toPoly :: [Integer] -> ExpQ toPoly as = foldl1 plusOp $ zipWith (\i c -> [| injectCoeff (modNat $(litE $ integerL c)) * var 0 ^ $(lift i) |]) [0 :: Integer ..] as buildInstance :: (Integer, Integer, [Integer]) -> DecsQ buildInstance (p,n,cs) = let tp = litT $ numTyLit p tn = litT $ numTyLit n in [d| instance {-# OVERLAPPING #-} ConwayPolynomial $tp $tn where conwayPolynomial _ _ = $(toPoly cs) {-# INLINE conwayPolynomial #-} |]