module Polynomial (
T, fromScalar, add, sub, neg, scale, mul,
differentiate, progression,
) where
type T a = [a]
fromScalar :: a -> [a]
fromScalar = (:[])
-- | add two polynomials or series
add :: Num a => [a] -> [a] -> [a]
{- zipWith (+) would cut the resulting list
to the length of the shorter operand -}
add [] ys = ys
add xs [] = xs
add (x:xs) (y:ys) = x+y : add xs ys
-- | subtract two polynomials or series
sub :: Num a => [a] -> [a] -> [a]
sub [] ys = map negate ys
sub xs [] = xs
sub (x:xs) (y:ys) = x-y : sub xs ys
neg :: Num a => [a] -> [a]
neg = map negate
-- | scale a polynomial or series by a factor
scale :: Num a => a -> [a] -> [a]
scale s = map (s*)
-- | multiply two polynomials or series
mul :: Num a => [a] -> [a] -> [a]
{- prevent from generation of many zeros
if the first operand is the empty list -}
mul [] = const []
mul xs = foldr (\y zs -> add (scale y xs) (0:zs)) []
progression :: Num a => [a]
progression = iterate (1+) 1
differentiate :: (Num a) => [a] -> [a]
differentiate x = zipWith (*) (tail x) progression