{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} {- | Maintainer : numericprelude@henning-thielemann.de Stability : provisional Portability : requires multi-parameter type classes Abstraction of bases of finite dimensional modules -} module Algebra.ModuleBasis where import qualified Number.Ratio as Ratio import qualified Algebra.PrincipalIdealDomain as PID import qualified Algebra.Module as Module -- import qualified Algebra.Additive as Additive import Algebra.Ring (one, fromInteger) import Algebra.Additive ((+), zero) import Data.List (map, length, (++)) import Prelude(Eq, (==), Bool, Int, Integer, Float, Double, asTypeOf, ) -- import qualified Prelude as P {- | It must hold: > Module.linearComb (flatten v `asTypeOf` [a]) (basis a) == v > dimension a v == length (flatten v `asTypeOf` [a]) -} class (Module.C a v) => C a v where {- | basis of the module with respect to the scalar type, the result must be independent of argument, 'Prelude.undefined' should suffice. -} basis :: a -> [v] -- | scale a vector by a scalar flatten :: v -> [a] {- | the size of the basis, should also work for undefined argument, the result must be independent of argument, 'Prelude.undefined' should suffice. -} dimension :: a -> v -> Int {-* Instances for atomic types -} instance C Float Float where basis _ = [one] flatten = (:[]) dimension _ _ = 1 instance C Double Double where basis _ = [one] flatten = (:[]) dimension _ _ = 1 instance C Int Int where basis _ = [one] flatten = (:[]) dimension _ _ = 1 instance C Integer Integer where basis _ = [one] flatten = (:[]) dimension _ _ = 1 instance (PID.C a) => C (Ratio.T a) (Ratio.T a) where basis _ = [one] flatten = (:[]) dimension _ _ = 1 {-* Instances for composed types -} instance (C a v0, C a v1) => C a (v0, v1) where basis s = map (\v -> (v,zero)) (basis s) ++ map (\v -> (zero,v)) (basis s) flatten (x0,x1) = flatten x0 ++ flatten x1 dimension s ~(x0,x1) = dimension s x0 + dimension s x1 instance (C a v0, C a v1, C a v2) => C a (v0, v1, v2) where basis s = map (\v -> (v,zero,zero)) (basis s) ++ map (\v -> (zero,v,zero)) (basis s) ++ map (\v -> (zero,zero,v)) (basis s) flatten (x0,x1,x2) = flatten x0 ++ flatten x1 ++ flatten x2 dimension s ~(x0,x1,x2) = dimension s x0 + dimension s x1 + dimension s x2 {- * Properties -} propFlatten :: (Eq v, C a v) => a -> v -> Bool propFlatten a v = Module.linearComb (flatten v `asTypeOf` [a]) (basis a) == v propDimension :: (C a v) => a -> v -> Bool propDimension a v = dimension a v == length (flatten v `asTypeOf` [a])