module SubHask.Category.Polynomial
where
import Data.List (intersperse,filter,reverse)
import qualified Prelude as P
import SubHask.Internal.Prelude
import SubHask.Category
import SubHask.Algebra
import SubHask.Monad
import SubHask.SubType
type Polynomial a = Polynomial_ a a
data Polynomial_ a b where
Polynomial_ :: (ValidLogic a, Ring a, a~b) => ![a] -> Polynomial_ a b
mkMutable [t| forall a b. Polynomial_ a b |]
instance (Eq r, Show r) => Show (Polynomial_ r r) where
show (Polynomial_ xs) = concat $ intersperse " + " $ filter (/=[]) $ reverse $ imap go xs
where
go :: Int -> r -> String
go 0 x = when (zero/=x) $ show x
go 1 x = when (zero/=x) $ when (one/=x) (show x) ++ "x"
go i x = when (zero/=x) $ when (one/=x) (show x) ++ "x^" ++ show i
when :: Monoid a => Bool -> a -> a
when cond x = if cond then x else zero
newtype instance ProofOf Polynomial_ a = ProofOf { unProofOf :: Polynomial_ a a }
mkMutable [t| forall a. ProofOf Polynomial_ a |]
instance Ring a => Semigroup (ProofOf Polynomial_ a) where
(ProofOf p1)+(ProofOf p2) = ProofOf $ p1+p2
instance (ValidLogic a, Ring a) => Cancellative (ProofOf Polynomial_ a) where
(ProofOf p1)(ProofOf p2) = ProofOf $ p1p2
instance (ValidLogic a, Ring a) => Monoid (ProofOf Polynomial_ a) where
zero = ProofOf zero
instance (Ring a, Abelian a) => Abelian (ProofOf Polynomial_ a)
instance (ValidLogic a, Ring a) => Group (ProofOf Polynomial_ a) where
negate (ProofOf p) = ProofOf $ negate p
instance (ValidLogic a, Ring a) => Rg (ProofOf Polynomial_ a) where
(ProofOf p1)*(ProofOf p2) = ProofOf $ p1*p2
instance (ValidLogic a, Ring a) => Rig (ProofOf Polynomial_ a) where
one = ProofOf one
instance (ValidLogic a, Ring a) => Ring (ProofOf Polynomial_ a) where
fromInteger i = ProofOf $ fromInteger i
provePolynomial :: (ValidLogic a, Ring a) => (ProofOf Polynomial_ a -> ProofOf Polynomial_ a) -> Polynomial_ a a
provePolynomial f = unProofOf $ f $ ProofOf $ Polynomial_ [0,1]
type instance Scalar (Polynomial_ a b) = Scalar b
type instance Logic (Polynomial_ a b) = Logic b
instance Eq b => Eq_ (Polynomial_ a b) where
(Polynomial_ xs)==(Polynomial_ ys) = xs==ys
instance Ring r => Semigroup (Polynomial_ r r) where
(Polynomial_ p1)+(Polynomial_ p2) = Polynomial_ $ sumList (+) p1 p2
instance (ValidLogic r, Ring r) => Monoid (Polynomial_ r r) where
zero = Polynomial_ []
instance (ValidLogic r, Ring r) => Cancellative (Polynomial_ r r) where
(Polynomial_ p1)(Polynomial_ p2) = Polynomial_ $ sumList () p1 p2
instance (ValidLogic r, Ring r) => Group (Polynomial_ r r) where
negate (Polynomial_ p) = Polynomial_ $ P.map negate p
instance (Ring r, Abelian r) => Abelian (Polynomial_ r r)
instance (ValidLogic r, Ring r) => Rg (Polynomial_ r r) where
(Polynomial_ p1)*(Polynomial_ p2) = Polynomial_ $ P.foldl (sumList (+)) [] $ go p1 zero
where
go [] i = []
go (x:xs) i = (P.replicate i zero ++ P.map (*x) p2):go xs (i+one)
instance (ValidLogic r, Ring r) => Rig (Polynomial_ r r) where
one = Polynomial_ [one]
instance (ValidLogic r, Ring r) => Ring (Polynomial_ r r) where
fromInteger i = Polynomial_ [fromInteger i]
type instance Polynomial_ r r >< r = Polynomial_ r r
instance IsScalar r => Module (Polynomial_ r r) where
(Polynomial_ xs) .* r = Polynomial_ $ P.map (*r) xs
instance IsScalar r => FreeModule (Polynomial_ r r) where
(Polynomial_ xs) .*. (Polynomial_ ys) = Polynomial_ $ P.zipWith (*) xs ys
ones = Polynomial_ $ P.repeat one
sumList f [] ys = ys
sumList f xs [] = xs
sumList f (x:xs) (y:ys) = f x y:sumList f xs ys
instance Category Polynomial_ where
type ValidCategory Polynomial_ a = (ValidLogic a, Ring a)
id = Polynomial_ [zero, one]
(Polynomial_ xs) . p2@(Polynomial_ _) = Polynomial_ (map (\x -> Polynomial_ [x]) xs) $ p2
instance Sup Polynomial_ Hask Hask
instance Sup Hask Polynomial_ Hask
instance Polynomial_ <: Hask where
embedType_ = Embed2 evalPolynomial_
pow :: Rig r => r -> Int -> r
pow r i = foldl' (*) one $ P.replicate i r
evalPolynomial_ :: Polynomial_ a b -> a -> b
evalPolynomial_ (Polynomial_ xs) r = sum $ imap go xs
where
go i x = x*pow r i