{-# LANGUAGE DataKinds, FlexibleInstances, GADTs, PolyKinds, TemplateHaskell #-} {-# LANGUAGE MultiParamTypeClasses, TypeFamilies #-} module Polynomial.Monomial ( -- * Types Monomial(..), Mon, SNat, Lex, Revlex, -- * Classes IsMonomialOrder, -- * Functions toMonomial ) where import Data.Function import Numeric.Algebra hiding ((+),(>)) import Prelude hiding (lex) import qualified Data.Sized as DS import qualified Data.Sequence as Seq import Data.Singletons.Prelude import GHC.TypeLits import Control.Lens (makeLenses, makeWrapped) type SNat (n :: Nat) = Sing n type Sized' n a = DS.Sized Seq.Seq n a type Mon n = Sized' n Int -- | Monomial is defined as an array of exponents newtype Monomial ord n = Monomial {getMonomial :: Mon n} deriving(Eq) ------------------------------------------ makeLenses ''Monomial makeWrapped ''Monomial showMonomial :: [Int] -> Int -> String showMonomial [] _ = "" showMonomial (x:xs) var | x == 0 = showMonomial xs (var+1) | x == 1 = "X_" ++ show var ++ showMonomial xs (var+1) | otherwise = "X_" ++ show var ++ "^" ++ show x ++ showMonomial xs (var+1) instance Show (Monomial ord n) where show monomial = showMonomial (DS.toList $ getMonomial monomial) 0 ------------------------------------------ -- | Definition of what a monomial order must meet class IsMonomialOrder (ord :: *) where compareMonomial :: Monomial ord n -> Monomial ord n -> Ordering ----------------------------- data Lex = Lex -- ^ Just the datatype for Lex ordering data Revlex = Revlex -- ^ Just the datatype for Revlex ordering lex :: Monomial ord n -> Monomial ord n -> Ordering lex = lex' `on` (DS.toList . getMonomial) lex' :: [Int] -> [Int] -> Ordering lex' [] [] = EQ lex' [] _ = LT lex' _ [] = GT lex' (x:xs) (y:ys) | (x == 0 && y == 0) || x==y = lex' xs ys | x > y = GT | otherwise = LT revlex :: Monomial ord n -> Monomial ord n -> Ordering revlex= revlex' `on` (DS.toList . getMonomial) revlex' :: [Int] -> [Int] -> Ordering revlex' [] [] = EQ revlex' [] _ = LT revlex' _ [] = GT revlex' x y | (xr == 0 && yr == 0) || xr==yr = revlex' (reverse xrs) (reverse yrs) | xr > yr = GT | otherwise = LT where (xr:xrs) = reverse x (yr:yrs) = reverse y -- | convert NAry list into Monomial. fromList :: SNat n -> [Int] -> Mon n fromList len = DS.fromListWithDefault len 0 toMonomial :: (IsMonomialOrder ord, KnownNat n) => [Int] -> Monomial ord n toMonomial a = Monomial $ fromList sing a instance IsMonomialOrder Lex where compareMonomial = lex instance IsMonomialOrder Revlex where compareMonomial = revlex instance (IsMonomialOrder ord) => Ord (Monomial ord n) where compare = compareMonomial instance (IsMonomialOrder ord, KnownNat n) => Unital (Monomial ord n) where one = toMonomial [] instance (IsMonomialOrder ord, KnownNat n) => Multiplicative (Monomial ord n) where (*) = prodMon prodMon :: (IsMonomialOrder ord, KnownNat n) => Monomial ord n -> Monomial ord n -> Monomial ord n prodMon mon1 mon2 | mon1 == one = mon2 | mon2 == one = mon1 | otherwise = toMonomial $ (zipWith (+) `on` (DS.toList . getMonomial)) mon1 mon2