qlinear-0.1.0.0: src/QLinear/Identity.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
module QLinear.Identity (e, Identity, HasIdentity (..)) where
import Data.Proxy
import qualified GHC.Natural as Natural
import GHC.TypeNats
import Internal.Matrix
type Identity n a = Matrix n n a
class HasIdentity a where
zero :: a
one :: a
instance (Num a) => HasIdentity a where
zero = 0
one = 1
-- | Polymirphic identity matrix
--
-- Identity matrix can udjust to other matrix with known size. If size is unknown, just set it yourself
--
-- >>> e :: Identity 4 Int
-- [1,0,0,0]
-- [0,1,0,0]
-- [0,0,1,0]
-- [0,0,0,1]
-- >>> e ~+~ [matrix| 1 2; 3 4 |]
-- [2,2]
-- [3,5]
e :: forall n a. (KnownNat n, HasIdentity a) => Identity n a
e = Matrix (n, n) $ finiteIdentityList (n, n) one zero
where
n = Natural.naturalToInt $ natVal (Proxy @n)
infiniteIdentityList :: a -> a -> [[a]]
infiniteIdentityList o z = stream (o : repeat z)
where
stream seed = seed : stream (z : seed)
finiteIdentityList :: (Int, Int) -> a -> a -> [[a]]
finiteIdentityList (m, n) o z = map (take n) $ take m $ infiniteIdentityList o z