{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoStarIsType #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module LAoP.Matrix.Nat
(
Matrix (..),
Countable,
CountableDimensions,
CountableN,
CountableNz,
CountableDimensionsN,
FromListsN,
FromListsNz,
Liftable,
TrivialE,
TrivialP,
empty,
one,
junc,
split,
I.FromNat,
I.Count,
I.Normalize,
I.FromLists,
fromLists,
toLists,
toList,
matrixBuilder,
row,
col,
zeros,
ones,
bang,
constant,
columns,
rows,
tr,
select,
cond,
abideJS,
abideSJ,
zipWithM,
(===),
p1,
p2,
(|||),
i1,
i2,
(-|-),
(><),
kp1,
kp2,
khatri,
identity,
comp,
fromF,
fromF',
pretty,
prettyPrint
)
where
import Data.Proxy
import GHC.TypeLits
import Control.DeepSeq
import qualified Control.Category as C
import qualified LAoP.Matrix.Internal as I
newtype Matrix e (cols :: Nat) (rows :: Nat) = M (I.Matrix e (I.FromNat cols) (I.FromNat rows))
deriving (Show, Num, Eq, Ord, NFData) via (I.Matrix e (I.FromNat cols) (I.FromNat rows))
type Countable a = KnownNat (I.Count a)
type CountableDimensions a b = (Countable a, Countable b)
type CountableN a = KnownNat (I.Count (I.FromNat a))
type CountableNz a = KnownNat (I.Count (I.Normalize a))
type CountableDimensionsN a b = (CountableN a, CountableN b)
type FromListsN e a b = I.FromLists e (I.FromNat a) (I.FromNat b)
type FromListsNz e a b = I.FromLists e (I.Normalize a) (I.Normalize b)
type Liftable e a b = (Bounded a, Bounded b, Enum a, Enum b, Eq b, Num e, Ord e)
type TrivialE a b = I.FromNat (a + b) ~ Either (I.FromNat a) (I.FromNat b)
type TrivialP a b = I.FromNat (a * b) ~ I.FromNat (I.Count (I.FromNat a) * I.Count (I.FromNat b))
instance (Num e) => C.Category (Matrix e) where
id = undefined
(.) = comp
empty :: Matrix e 0 0
empty = M I.Empty
one :: e -> Matrix e 1 1
one = M . I.One
junc ::
(TrivialE a b) =>
Matrix e a rows ->
Matrix e b rows ->
Matrix e (a + b) rows
junc (M a) (M b) = M (I.Junc a b)
infixl 3 |||
(|||) ::
(TrivialE a b) =>
Matrix e a rows ->
Matrix e b rows ->
Matrix e (a + b) rows
(|||) = junc
split ::
(TrivialE a b) =>
Matrix e cols a ->
Matrix e cols b ->
Matrix e cols (a + b)
split (M a) (M b) = M (I.Split a b)
infixl 2 ===
(===) ::
(TrivialE a b) =>
Matrix e cols a ->
Matrix e cols b ->
Matrix e cols (a + b)
(===) = split
fromLists :: (FromListsN e cols rows) => [[e]] -> Matrix e cols rows
fromLists = M . I.fromLists
matrixBuilder ::
(FromListsN e cols rows, CountableN cols, CountableN rows)
=> ((Int, Int) -> e) -> Matrix e cols rows
matrixBuilder = M . I.matrixBuilder
col :: (I.FromLists e () (I.FromNat rows)) => [e] -> Matrix e 1 rows
col = M . I.col
row :: (I.FromLists e (I.FromNat cols) ()) => [e] -> Matrix e cols 1
row = M . I.row
fromF ::
( Liftable e a b,
CountableN cols,
CountableN rows,
FromListsN e rows cols
) =>
(a -> b) ->
Matrix e cols rows
fromF = M . I.fromF
fromF' ::
( Liftable e a b,
CountableNz a,
CountableNz b,
FromListsNz e b a
) =>
(a -> b) ->
Matrix e (I.Count a) (I.Count b)
fromF' = undefined
toLists :: Matrix e cols rows -> [[e]]
toLists (M m) = I.toLists m
toList :: Matrix e cols rows -> [e]
toList (M m) = I.toList m
zeros ::
(Num e, FromListsN e cols rows, CountableN cols, CountableN rows) =>
Matrix e cols rows
zeros = M I.zeros
ones ::
(Num e, FromListsN e cols rows, CountableN cols, CountableN rows) =>
Matrix e cols rows
ones = M I.ones
constant ::
(Num e, FromListsN e cols rows, CountableN cols, CountableN rows) =>
e ->
Matrix e cols rows
constant = M . I.constant
bang ::
forall e cols.
(Num e, Enum e, I.FromLists e (I.FromNat cols) (), CountableN cols) =>
Matrix e cols 1
bang = M I.bang
identity ::
(Num e, FromListsN e cols cols, CountableN cols) =>
Matrix e cols cols
identity = M I.identity
comp :: (Num e) => Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
comp (M a) (M b) = M (I.comp a b)
p1 ::
( Num e,
CountableDimensionsN n m,
FromListsN e n m,
FromListsN e m m,
TrivialE m n
) =>
Matrix e (m + n) m
p1 = M I.p1
p2 ::
( Num e,
CountableDimensionsN n m,
FromListsN e m n,
FromListsN e n n,
TrivialE m n
) =>
Matrix e (m + n) n
p2 = M I.p2
i1 ::
( Num e,
CountableDimensionsN n rows,
FromListsN e n rows,
FromListsN e rows rows,
TrivialE rows n
) =>
Matrix e rows (rows + n)
i1 = tr p1
i2 ::
( Num e,
CountableDimensionsN rows m,
FromListsN e m rows,
FromListsN e rows rows,
TrivialE m rows
) =>
Matrix e rows (m + rows)
i2 = tr p2
rows :: (CountableN rows) => Matrix e cols rows -> Int
rows (M m) = I.rows m
columns :: (CountableN cols) => Matrix e cols rows -> Int
columns (M m) = I.columns m
infixl 5 -|-
(-|-) ::
( Num e,
CountableDimensionsN j k,
FromListsN e k k,
FromListsN e j k,
FromListsN e k j,
FromListsN e j j,
TrivialE n m,
TrivialE k j
) =>
Matrix e n k ->
Matrix e m j ->
Matrix e (n + m) (k + j)
(-|-) (M a) (M b) = M ((I.-|-) a b)
kp1 ::
forall e m k .
( Num e,
CountableDimensionsN m k,
CountableN (m * k),
FromListsN e (m * k) m,
TrivialP m k
) => Matrix e (m * k) m
kp1 = M (I.kp1 @e @(I.FromNat m) @(I.FromNat k))
kp2 ::
forall e m k.
( Num e,
CountableDimensionsN k m,
FromListsN e (m * k) k,
CountableN (m * k),
TrivialP m k
) => Matrix e (m * k) k
kp2 = M (I.kp2 @e @(I.FromNat m) @(I.FromNat k))
khatri ::
forall e cols a b.
( Num e,
CountableDimensionsN a b,
CountableN (a * b),
FromListsN e (a * b) a,
FromListsN e (a * b) b,
TrivialP a b
) => Matrix e cols a -> Matrix e cols b -> Matrix e cols (a * b)
khatri a b =
let kp1' = kp1 @e @a @b
kp2' = kp2 @e @a @b
in comp (tr kp1') a * comp (tr kp2') b
infixl 4 ><
(><) ::
forall e m p n q.
( Num e,
CountableDimensionsN m n,
CountableDimensionsN p q,
CountableDimensionsN (m * n) (p * q),
FromListsN e (m * n) m,
FromListsN e (m * n) n,
FromListsN e (p * q) p,
FromListsN e (p * q) q,
TrivialP m n,
TrivialP p q
) => Matrix e m p -> Matrix e n q -> Matrix e (m * n) (p * q)
(><) a b =
let kp1' = kp1 @e @m @n
kp2' = kp2 @e @m @n
in khatri (comp a kp1') (comp b kp2')
abideJS :: Matrix e cols rows -> Matrix e cols rows
abideJS (M m) = M (I.abideJS m)
abideSJ :: Matrix e cols rows -> Matrix e cols rows
abideSJ (M m) = M (I.abideSJ m)
tr :: Matrix e cols rows -> Matrix e rows cols
tr (M m) = M (I.tr m)
select ::
( Num e,
FromListsN e rows1 rows1,
CountableN rows1,
I.FromNat rows2 ~ I.FromNat rows1,
I.FromNat cols1 ~ I.FromNat cols2,
I.FromNat rows3 ~ Either (I.FromNat cols3) (I.FromNat rows1)
) => Matrix e cols1 rows3 -> Matrix e cols3 rows1 -> Matrix e cols2 rows2
select (M m) (M y) = M (I.select m y)
cond ::
( I.FromNat (I.Count (I.FromNat cols)) ~ I.FromNat cols,
CountableN cols,
I.FromLists e () (I.FromNat cols),
I.FromLists e (I.FromNat cols) (),
FromListsN e cols cols,
Liftable e a Bool
)
=>
(a -> Bool) -> Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
cond p (M a) (M b) = M (I.cond p a b)
pretty :: (CountableDimensionsN cols rows, Show e) => Matrix e cols rows -> String
pretty (M m) = I.pretty m
prettyPrint :: (CountableDimensionsN cols rows, Show e) => Matrix e cols rows -> IO ()
prettyPrint (M m) = I.prettyPrint m
zipWithM :: (e -> f -> g) -> Matrix e cols rows -> Matrix f cols rows -> Matrix g cols rows
zipWithM f (M a) (M b) = M (I.zipWithM f a b)