{-# 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,
join,
fork,
I.FromNat,
I.Count,
I.Normalize,
I.FromLists,
fromLists,
toLists,
toList,
matrixBuilder',
row,
col,
zeros,
ones,
bang,
constant,
columns,
rows,
tr,
(.|),
(./),
select,
cond,
abideJF,
abideFJ,
zipWithM,
(===),
p1,
p2,
(|||),
i1,
i2,
(-|-),
(><),
fstM,
sndM,
kr,
iden,
comp,
fromF',
fromF,
pretty,
prettyPrint
)
where
import Data.Proxy
import GHC.TypeLits
import Control.DeepSeq
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))
empty :: Matrix e 0 0
empty = M I.Empty
one :: e -> Matrix e 1 1
one = M . I.One
join ::
(TrivialE a b) =>
Matrix e a rows ->
Matrix e b rows ->
Matrix e (a + b) rows
join (M a) (M b) = M (I.Join a b)
infixl 3 |||
(|||) ::
(TrivialE a b) =>
Matrix e a rows ->
Matrix e b rows ->
Matrix e (a + b) rows
(|||) = join
fork ::
(TrivialE a b) =>
Matrix e cols a ->
Matrix e cols b ->
Matrix e cols (a + b)
fork (M a) (M b) = M (I.Fork a b)
infixl 2 ===
(===) ::
(TrivialE a b) =>
Matrix e cols a ->
Matrix e cols b ->
Matrix e cols (a + b)
(===) = fork
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
iden ::
(Num e, FromListsN e cols cols, CountableN cols) =>
Matrix e cols cols
iden = M I.iden
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)
infixl 7 .|
(.|) :: Num e => e -> Matrix e cols rows -> Matrix e cols rows
(.|) e (M m) = M (e I..| m)
infixl 7 ./
(./) :: Fractional e => Matrix e cols rows -> e -> Matrix e cols rows
(./) (M m) e = M (m I../ e)
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)
fstM ::
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
fstM = M (I.fstM @e @(I.FromNat m) @(I.FromNat k))
sndM ::
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
sndM = M (I.sndM @e @(I.FromNat m) @(I.FromNat k))
kr ::
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)
kr a b =
let fstM' = fstM @e @a @b
sndM' = sndM @e @a @b
in comp (tr fstM') a * comp (tr sndM') 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 fstM' = fstM @e @m @n
sndM' = sndM @e @m @n
in kr (comp a fstM') (comp b sndM')
abideJF :: Matrix e cols rows -> Matrix e cols rows
abideJF (M m) = M (I.abideJF m)
abideFJ :: Matrix e cols rows -> Matrix e cols rows
abideFJ (M m) = M (I.abideFJ 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)