{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoStarIsType #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

-----------------------------------------------------------------------------
-- |
-- Module     : LAoP.Matrix.Type
-- Copyright  : (c) Armando Santos 2019-2020
-- Maintainer : armandoifsantos@gmail.com
-- Stability  : experimental
--
-- The LAoP discipline generalises relations and functions treating them as
-- Boolean matrices and in turn consider these as arrows.
--
-- __LAoP__ is a library for algebraic (inductive) construction and manipulation of matrices
-- in Haskell. See <https://github.com/bolt12/master-thesis my Msc Thesis> for the
-- motivation behind the library, the underlying theory, and implementation details.
--
-- This module offers a newtype wrapper around 'Matrix.Type.Matrix' that
-- uses arbitrary types instead of canonical data types for the matrices
-- dimensions.
--
-- __NOTE__: If the types in the dimensions are custom they must need to
-- implement a 'Generic' instance.
--
-----------------------------------------------------------------------------

module LAoP.Matrix.Type
  ( -- | LAoP (Linear Algebra of Programming) Inductive Matrix definition.
    --
    --   LAoP generalises relations and functions treating them as
    --   Boolean matrices and in turn consider these as arrows.
    --   This library offers many of the combinators mentioned in the work of
    --   Macedo (2012) and Oliveira (2012).
    --
    --   This definition is a wrapper around 'Matrix.Type' but
    --   dimensions are arbitrary data types. Type inference might not
    --   be as desired.

    -- __NOTE__: If the types in the dimensions are custom they must need to
    -- implement a 'Generic' instance.
    --

    -- * Type safe matrix representation
    Matrix (..),

    -- * Constraint type aliases
    Countable,
    CountableDims,
    CountableN,
    CountableDimsN,
    FLN,
    Liftable,
    Trivial,
    TrivialP,

    -- * Type aliases
    Zero,
    One,

    -- * Primitives
    one,
    join,
    fork,

    -- * Auxiliary type families
    I.FromNat,
    I.Count,
    I.Normalize,

    -- * Matrix construction and conversion
    I.FromLists,
    fromLists,
    toLists,
    toList,
    matrixBuilder',
    matrixBuilder,
    row,
    col,
    zeros,
    ones,
    bang,
    point,
    constant,

    -- * Functor instance equivalent function
    fmapM,
    bimapM,

    -- * Applicative/Monoidal instance equivalent functions
    unitM,
    multM,

    -- * Selective equivalent instance function
    selectM,

    -- * Monad equivalent instance function
    returnM,
    bindM,

    -- * Misc
    -- ** Get dimensions
    columns,
    columns',
    rows,
    rows',

    -- ** Matrix Transposition
    tr,

    -- ** Scalar multiplication/division of matrices
    (.|),
    (./),

    -- ** McCarthy's Conditional
    cond,

    -- ** Matrix "abiding"
    abideJF,
    abideFJ,

    -- ** Zip Matrices
    zipWithM,

    -- * Biproduct approach
    -- ** Fork
    (===),
    -- *** Projections
    p1,
    p2,
    -- ** Join
    (|||),
    -- *** Injections
    i1,
    i2,
    -- ** Bifunctors
    (-|-),
    (><),

    -- ** Applicative matrix combinators

    -- | Note that given the restrictions imposed it is not possible to
    -- implement the standard type classes present in standard Haskell.
    -- *** Matrix pairing projections
    fstM,
    sndM,

    -- *** Matrix pairing
    kr,

    -- * Matrix composition and lifting

    -- ** Arrow matrix combinators

    -- | Note that given the restrictions imposed it is not possible to
    -- implement the standard type classes present in standard Haskell.
    iden,
    comp,
    fromF',
    fromF,

    -- * Relation
    toRel,

    -- * Matrix printing
    pretty,
    prettyPrint
  )
where

import Data.Void
import Data.Proxy
import Data.Kind
import GHC.TypeLits
import Control.DeepSeq
import LAoP.Utils
import qualified LAoP.Matrix.Internal as I
import Prelude hiding (id, (.))

newtype Matrix e (cols :: Type) (rows :: Type) = M (I.Matrix e (I.Normalize cols) (I.Normalize rows))
  deriving (Int -> Matrix e cols rows -> ShowS
[Matrix e cols rows] -> ShowS
Matrix e cols rows -> String
(Int -> Matrix e cols rows -> ShowS)
-> (Matrix e cols rows -> String)
-> ([Matrix e cols rows] -> ShowS)
-> Show (Matrix e cols rows)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall e cols rows. Show e => Int -> Matrix e cols rows -> ShowS
forall e cols rows. Show e => [Matrix e cols rows] -> ShowS
forall e cols rows. Show e => Matrix e cols rows -> String
showList :: [Matrix e cols rows] -> ShowS
$cshowList :: forall e cols rows. Show e => [Matrix e cols rows] -> ShowS
show :: Matrix e cols rows -> String
$cshow :: forall e cols rows. Show e => Matrix e cols rows -> String
showsPrec :: Int -> Matrix e cols rows -> ShowS
$cshowsPrec :: forall e cols rows. Show e => Int -> Matrix e cols rows -> ShowS
Show, Integer -> Matrix e cols rows
Matrix e cols rows -> Matrix e cols rows
Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
(Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows)
-> (Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows)
-> (Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows)
-> (Matrix e cols rows -> Matrix e cols rows)
-> (Matrix e cols rows -> Matrix e cols rows)
-> (Matrix e cols rows -> Matrix e cols rows)
-> (Integer -> Matrix e cols rows)
-> Num (Matrix e cols rows)
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
forall e cols rows. Num e => Integer -> Matrix e cols rows
forall e cols rows.
Num e =>
Matrix e cols rows -> Matrix e cols rows
forall e cols rows.
Num e =>
Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
fromInteger :: Integer -> Matrix e cols rows
$cfromInteger :: forall e cols rows. Num e => Integer -> Matrix e cols rows
signum :: Matrix e cols rows -> Matrix e cols rows
$csignum :: forall e cols rows.
Num e =>
Matrix e cols rows -> Matrix e cols rows
abs :: Matrix e cols rows -> Matrix e cols rows
$cabs :: forall e cols rows.
Num e =>
Matrix e cols rows -> Matrix e cols rows
negate :: Matrix e cols rows -> Matrix e cols rows
$cnegate :: forall e cols rows.
Num e =>
Matrix e cols rows -> Matrix e cols rows
* :: Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
$c* :: forall e cols rows.
Num e =>
Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
- :: Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
$c- :: forall e cols rows.
Num e =>
Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
+ :: Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
$c+ :: forall e cols rows.
Num e =>
Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
Num, Matrix e cols rows -> Matrix e cols rows -> Bool
(Matrix e cols rows -> Matrix e cols rows -> Bool)
-> (Matrix e cols rows -> Matrix e cols rows -> Bool)
-> Eq (Matrix e cols rows)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall e cols rows.
Eq e =>
Matrix e cols rows -> Matrix e cols rows -> Bool
/= :: Matrix e cols rows -> Matrix e cols rows -> Bool
$c/= :: forall e cols rows.
Eq e =>
Matrix e cols rows -> Matrix e cols rows -> Bool
== :: Matrix e cols rows -> Matrix e cols rows -> Bool
$c== :: forall e cols rows.
Eq e =>
Matrix e cols rows -> Matrix e cols rows -> Bool
Eq, Eq (Matrix e cols rows)
Eq (Matrix e cols rows)
-> (Matrix e cols rows -> Matrix e cols rows -> Ordering)
-> (Matrix e cols rows -> Matrix e cols rows -> Bool)
-> (Matrix e cols rows -> Matrix e cols rows -> Bool)
-> (Matrix e cols rows -> Matrix e cols rows -> Bool)
-> (Matrix e cols rows -> Matrix e cols rows -> Bool)
-> (Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows)
-> (Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows)
-> Ord (Matrix e cols rows)
Matrix e cols rows -> Matrix e cols rows -> Bool
Matrix e cols rows -> Matrix e cols rows -> Ordering
Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall e cols rows. Ord e => Eq (Matrix e cols rows)
forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Bool
forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Ordering
forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
min :: Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
$cmin :: forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
max :: Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
$cmax :: forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
>= :: Matrix e cols rows -> Matrix e cols rows -> Bool
$c>= :: forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Bool
> :: Matrix e cols rows -> Matrix e cols rows -> Bool
$c> :: forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Bool
<= :: Matrix e cols rows -> Matrix e cols rows -> Bool
$c<= :: forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Bool
< :: Matrix e cols rows -> Matrix e cols rows -> Bool
$c< :: forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Bool
compare :: Matrix e cols rows -> Matrix e cols rows -> Ordering
$ccompare :: forall e cols rows.
Ord e =>
Matrix e cols rows -> Matrix e cols rows -> Ordering
$cp1Ord :: forall e cols rows. Ord e => Eq (Matrix e cols rows)
Ord, Matrix e cols rows -> ()
(Matrix e cols rows -> ()) -> NFData (Matrix e cols rows)
forall a. (a -> ()) -> NFData a
forall e cols rows. NFData e => Matrix e cols rows -> ()
rnf :: Matrix e cols rows -> ()
$crnf :: forall e cols rows. NFData e => Matrix e cols rows -> ()
NFData) via (I.Matrix e (I.Normalize cols) (I.Normalize rows))

-- | Constraint type synonyms to keep the type signatures less convoluted
type Countable a        = KnownNat (I.Count a)
type CountableDims a b  = (Countable a, Countable b)
type CountableN a       = KnownNat (I.Count (I.Normalize a))
type CountableDimsN a b = (CountableN a, CountableN b)
type FLN a b            = I.FromLists (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 Trivial a          = I.Normalize (I.Normalize a) ~ I.Normalize (I.Normalize (I.Normalize a))
type Trivial2 a         = I.Normalize a ~ I.Normalize (I.Normalize a)
type Trivial3 a         = I.FromNat (I.Count (I.Normalize (I.Normalize a))) ~ I.Normalize (I.Normalize a)
type TrivialP a b       = I.Normalize (a, b) ~ I.Normalize (I.Normalize a, I.Normalize b)

-- | It is possible to implement a constrained version of the category type
-- class.
instance (Num e) => Category (Matrix e) where
  type Object (Matrix e) a = (FLN a a, CountableN a)
  id :: Matrix e a a
id = Matrix e a a
forall e a. (Num e, FLN a a, CountableN a) => Matrix e a a
iden
  . :: Matrix e b c -> Matrix e a b -> Matrix e a c
(.) = Matrix e b c -> Matrix e a b -> Matrix e a c
forall e cr rows cols.
Num e =>
Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
comp

-- | Bifunctor equivalent function
bimapM ::
       ( Liftable e a b,
         Liftable e c d,
         CountableDimsN a c,
         CountableDimsN b d,
         FLN d c,
         FLN b a
       ) => (a -> b) -> (c -> d) -> Matrix e a c -> Matrix e b d
bimapM :: (a -> b) -> (c -> d) -> Matrix e a c -> Matrix e b d
bimapM a -> b
f c -> d
g Matrix e a c
m = (c -> d) -> Matrix e c d
forall e a b.
(Liftable e a b, CountableDimsN a b, FLN b a) =>
(a -> b) -> Matrix e a b
fromF c -> d
g Matrix e c d -> Matrix e a c -> Matrix e a d
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. Matrix e a c
m Matrix e a d -> Matrix e b a -> Matrix e b d
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. Matrix e a b -> Matrix e b a
forall e cols rows. Matrix e cols rows -> Matrix e rows cols
tr ((a -> b) -> Matrix e a b
forall e a b.
(Liftable e a b, CountableDimsN a b, FLN b a) =>
(a -> b) -> Matrix e a b
fromF a -> b
f)

-- | Zero type alias
type Zero = Void

-- | One type alias
type One = ()

-- Primitives

-- | Unit matrix constructor
one :: e -> Matrix e One One
one :: e -> Matrix e () ()
one = Matrix e () () -> Matrix e () ()
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e () () -> Matrix e () ())
-> (e -> Matrix e () ()) -> e -> Matrix e () ()
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. e -> Matrix e () ()
forall e. e -> Matrix e () ()
I.One

-- | Matrix 'Join' constructor
join ::
  Matrix e a rows ->
  Matrix e b rows ->
  Matrix e (Either a b) rows
join :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
join (M Matrix e (Normalize a) (Normalize rows)
a) (M Matrix e (Normalize b) (Normalize rows)
b) = Matrix e (Normalize (Either a b)) (Normalize rows)
-> Matrix e (Either a b) rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize a) (Normalize rows)
-> Matrix e (Normalize b) (Normalize rows)
-> Matrix e (Either (Normalize a) (Normalize b)) (Normalize rows)
forall e a rows b.
Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
I.Join Matrix e (Normalize a) (Normalize rows)
a Matrix e (Normalize b) (Normalize rows)
b)

infixl 3 |||
-- | Matrix 'Join' constructor
(|||) ::
  Matrix e a rows ->
  Matrix e b rows ->
  Matrix e (Either a b) rows
||| :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
(|||) = Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
forall e a rows b.
Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
join

-- | Matrix 'Fork' constructor
fork ::
  Matrix e cols a ->
  Matrix e cols b ->
  Matrix e cols (Either a b)
fork :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
fork (M Matrix e (Normalize cols) (Normalize a)
a) (M Matrix e (Normalize cols) (Normalize b)
b) = Matrix e (Normalize cols) (Normalize (Either a b))
-> Matrix e cols (Either a b)
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Normalize a)
-> Matrix e (Normalize cols) (Normalize b)
-> Matrix e (Normalize cols) (Either (Normalize a) (Normalize b))
forall e cols a b.
Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
I.Fork Matrix e (Normalize cols) (Normalize a)
a Matrix e (Normalize cols) (Normalize b)
b)

infixl 2 ===
-- | Matrix 'Fork' constructor
(===) ::
  Matrix e cols a ->
  Matrix e cols b ->
  Matrix e cols (Either a b)
=== :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
(===) = Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
forall e cols a b.
Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
fork

-- Functor hierarchy

-- | Functor instance equivalent function
fmapM ::
     ( Liftable e a b,
       CountableDimsN a b,
       FLN b a
     )
     =>
     (a -> b) -> Matrix e c a -> Matrix e c b
fmapM :: (a -> b) -> Matrix e c a -> Matrix e c b
fmapM a -> b
f Matrix e c a
m = (a -> b) -> Matrix e a b
forall e a b.
(Liftable e a b, CountableDimsN a b, FLN b a) =>
(a -> b) -> Matrix e a b
fromF a -> b
f Matrix e a b -> Matrix e c a -> Matrix e c b
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. Matrix e c a
m

-- | Applicative instance equivalent 'unit' function,
unitM :: (Num e) => Matrix e () ()
unitM :: Matrix e () ()
unitM = e -> Matrix e () ()
forall e. e -> Matrix e () ()
one e
1

-- | Applicative instance equivalent 'unit' function,
multM ::
      ( CountableDimsN a b,
        CountableN (a, b),
        Num e,
        FLN (a, b) a,
        FLN (a, b) b,
        TrivialP a b
      ) => Matrix e c a -> Matrix e c b -> Matrix e c (a, b)
multM :: Matrix e c a -> Matrix e c b -> Matrix e c (a, b)
multM = Matrix e c a -> Matrix e c b -> Matrix e c (a, b)
forall e cols a b.
(Num e, CountableDimsN a b, CountableN (a, b), FLN (a, b) a,
 FLN (a, b) b, TrivialP a b) =>
Matrix e cols a -> Matrix e cols b -> Matrix e cols (a, b)
kr

-- | Monad instance equivalent 'return' function,
returnM ::
        forall e a .
        ( Num e,
          Enum e,
          Enum a,
          FLN () a,
          Countable a
        ) => a -> Matrix e One a
returnM :: a -> Matrix e () a
returnM a
a = [e] -> Matrix e () a
forall rows e. FLN () rows => [e] -> Matrix e () rows
col [e]
l
    where
        i :: Int
i = Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy (Count a) -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy (Count a)
forall k (t :: k). Proxy t
Proxy :: Proxy (I.Count a))
        x :: Int
x = a -> Int
forall a. Enum a => a -> Int
fromEnum a
a
        l :: [e]
l = Int -> [e] -> [e]
forall a. Int -> [a] -> [a]
take Int
x [e
0,e
0..] [e] -> [e] -> [e]
forall a. [a] -> [a] -> [a]
++ [e
1] [e] -> [e] -> [e]
forall a. [a] -> [a] -> [a]
++ Int -> [e] -> [e]
forall a. Int -> [a] -> [a]
take (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [e
0,e
0..]

-- | Monad instance equivalent '(>>=)' function,
bindM :: (Num e) => Matrix e a b -> Matrix e b c -> Matrix e a c
bindM :: Matrix e a b -> Matrix e b c -> Matrix e a c
bindM = (Matrix e b c -> Matrix e a b -> Matrix e a c)
-> Matrix e a b -> Matrix e b c -> Matrix e a c
forall a b c. (a -> b -> c) -> b -> a -> c
flip Matrix e b c -> Matrix e a b -> Matrix e a c
forall e cr rows cols.
Num e =>
Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
comp

-- Construction

-- | Build a matrix out of a list of list of elements. Throws a runtime
-- error if the dimensions do not match.
fromLists :: (FLN cols rows) => [[e]] -> Matrix e cols rows
fromLists :: [[e]] -> Matrix e cols rows
fromLists = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows)
-> ([[e]] -> Matrix e (Normalize cols) (Normalize rows))
-> [[e]]
-> Matrix e cols rows
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. [[e]] -> Matrix e (Normalize cols) (Normalize rows)
forall cols rows e.
FromLists cols rows =>
[[e]] -> Matrix e cols rows
I.fromLists

-- | Matrix builder function. Constructs a matrix provided with
-- a construction function that operates with indices.
matrixBuilder' ::
  (FLN cols rows, CountableDimsN cols rows )
  => ((Int, Int) -> e) -> Matrix e cols rows
matrixBuilder' :: ((Int, Int) -> e) -> Matrix e cols rows
matrixBuilder' = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows)
-> (((Int, Int) -> e)
    -> Matrix e (Normalize cols) (Normalize rows))
-> ((Int, Int) -> e)
-> Matrix e cols rows
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. ((Int, Int) -> e) -> Matrix e (Normalize cols) (Normalize rows)
forall e cols rows.
(FL cols rows, CountableDims cols rows) =>
((Int, Int) -> e) -> Matrix e cols rows
I.matrixBuilder'

-- | Matrix builder function. Constructs a matrix provided with
-- a construction function that operates with arbitrary types.
matrixBuilder ::
  ( FLN a b,
    Enum a,
    Enum b,
    Bounded a,
    Bounded b,
    Eq a,
    CountableDimsN a b
  ) => ((a, b) -> e) -> Matrix e a b
matrixBuilder :: ((a, b) -> e) -> Matrix e a b
matrixBuilder (a, b) -> e
f = Matrix e (Normalize a) (Normalize b) -> Matrix e a b
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (((a, b) -> e) -> Matrix e (Normalize a) (Normalize b)
forall e a b.
(FLN a b, CountableN b, Enum a, Enum b, Bounded a, Bounded b, Eq a,
 CountableDimsN a b) =>
((a, b) -> e) -> Matrix e (Normalize a) (Normalize b)
I.matrixBuilder (a, b) -> e
f)

-- | Constructs a column vector matrix
col :: (FLN () rows) => [e] -> Matrix e One rows
col :: [e] -> Matrix e () rows
col = Matrix e () (Normalize rows) -> Matrix e () rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e () (Normalize rows) -> Matrix e () rows)
-> ([e] -> Matrix e () (Normalize rows)) -> [e] -> Matrix e () rows
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. [e] -> Matrix e () (Normalize rows)
forall rows e. FL () rows => [e] -> Matrix e () rows
I.col

-- | Constructs a row vector matrix
row :: (FLN cols ()) => [e] -> Matrix e cols One
row :: [e] -> Matrix e cols ()
row = Matrix e (Normalize cols) () -> Matrix e cols ()
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) () -> Matrix e cols ())
-> ([e] -> Matrix e (Normalize cols) ()) -> [e] -> Matrix e cols ()
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. [e] -> Matrix e (Normalize cols) ()
forall cols e. FL cols () => [e] -> Matrix e cols ()
I.row

-- | Lifts functions to matrices with arbitrary dimensions.
--
--   NOTE: Be careful to not ask for a matrix bigger than the cardinality of
-- types @a@ or @b@ allows.
fromF' ::
  ( Liftable e a b,
    CountableDimsN cols rows,
    FLN rows cols
  ) =>
  (a -> b) -> Matrix e cols rows
fromF' :: (a -> b) -> Matrix e cols rows
fromF' = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows)
-> ((a -> b) -> Matrix e (Normalize cols) (Normalize rows))
-> (a -> b)
-> Matrix e cols rows
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. (a -> b) -> Matrix e (Normalize cols) (Normalize rows)
forall a b cols rows e.
(Liftable e a b, CountableDims cols rows, FL rows cols) =>
(a -> b) -> Matrix e cols rows
I.fromF'

-- | Lifts functions to matrices with dimensions matching @a@ and @b@
-- cardinality's.
fromF ::
  ( Liftable e a b,
    CountableDimsN a b,
    FLN b a
  ) =>
  (a -> b) -> Matrix e a b
fromF :: (a -> b) -> Matrix e a b
fromF = Matrix e (Normalize a) (Normalize b) -> Matrix e a b
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize a) (Normalize b) -> Matrix e a b)
-> ((a -> b) -> Matrix e (Normalize a) (Normalize b))
-> (a -> b)
-> Matrix e a b
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. (a -> b) -> Matrix e (Normalize a) (Normalize b)
forall a b e.
(Liftable e a b, CountableDimsN a b, FLN b a) =>
(a -> b) -> Matrix e (Normalize a) (Normalize b)
I.fromF

-- | Lifts relation functions to Boolean Matrix
toRel ::
  ( Liftable (Natural 0 1) a b,
    CountableDimsN a b,
    FLN b a
  ) => (a -> b -> Bool) -> Matrix (Natural 0 1) a b
toRel :: (a -> b -> Bool) -> Matrix (Natural 0 1) a b
toRel = Matrix (Natural 0 1) (Normalize a) (Normalize b)
-> Matrix (Natural 0 1) a b
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix (Natural 0 1) (Normalize a) (Normalize b)
 -> Matrix (Natural 0 1) a b)
-> ((a -> b -> Bool)
    -> Matrix (Natural 0 1) (Normalize a) (Normalize b))
-> (a -> b -> Bool)
-> Matrix (Natural 0 1) a b
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. (a -> b -> Bool)
-> Matrix (Natural 0 1) (Normalize a) (Normalize b)
forall a b.
(Bounded a, Bounded b, Enum a, Enum b, Eq b, CountableDimsN a b,
 FLN b a) =>
(a -> b -> Bool) -> Relation (Normalize a) (Normalize b)
I.toRel

-- Conversion

-- | Converts a matrix to a list of lists of elements.
toLists :: Matrix e cols rows -> [[e]]
toLists :: Matrix e cols rows -> [[e]]
toLists (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> [[e]]
forall e cols rows. Matrix e cols rows -> [[e]]
I.toLists Matrix e (Normalize cols) (Normalize rows)
m

-- | Converts a matrix to a list of elements.
toList :: Matrix e cols rows -> [e]
toList :: Matrix e cols rows -> [e]
toList (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> [e]
forall e cols rows. Matrix e cols rows -> [e]
I.toList Matrix e (Normalize cols) (Normalize rows)
m

-- Zeros Matrix

-- | The zero matrix. A matrix wholly filled with zeros.
zeros ::
  (Num e, FLN cols rows, CountableDimsN cols rows)
  => Matrix e cols rows
zeros :: Matrix e cols rows
zeros = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M Matrix e (Normalize cols) (Normalize rows)
forall e cols rows.
(Num e, FL cols rows, CountableDims cols rows) =>
Matrix e cols rows
I.zeros

-- Ones Matrix

-- | The ones matrix. A matrix wholly filled with ones.
--
--   Also known as T (Top) matrix.
ones ::
  (Num e, FLN cols rows, CountableDimsN cols rows)
  => Matrix e cols rows
ones :: Matrix e cols rows
ones = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M Matrix e (Normalize cols) (Normalize rows)
forall e cols rows.
(Num e, FL cols rows, CountableDims cols rows) =>
Matrix e cols rows
I.ones

-- Const Matrix

-- | The constant matrix constructor. A matrix wholly filled with a given
-- value.
constant ::
  (Num e, FLN cols rows, CountableDimsN cols rows)
  => e -> Matrix e cols rows
constant :: e -> Matrix e cols rows
constant = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows)
-> (e -> Matrix e (Normalize cols) (Normalize rows))
-> e
-> Matrix e cols rows
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. e -> Matrix e (Normalize cols) (Normalize rows)
forall e cols rows.
(Num e, FL cols rows, CountableDims cols rows) =>
e -> Matrix e cols rows
I.constant

-- Bang Matrix

-- | The T (Top) row vector matrix.
bang ::
  forall e cols.
  (Num e, Enum e, FLN cols (), CountableN cols) =>
  Matrix e cols One
bang :: Matrix e cols ()
bang = Matrix e (Normalize cols) (Normalize ()) -> Matrix e cols ()
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M Matrix e (Normalize cols) (Normalize ())
forall e cols.
(Num e, Enum e, FL cols (), Countable cols) =>
Matrix e cols ()
I.bang

-- | Point constant relation
point ::
      ( Bounded a,
        Enum a,
        Eq a,
        Num e,
        Ord e,
        CountableN a,
        FLN a One
      ) => a -> Matrix e One a
point :: a -> Matrix e () a
point = (() -> a) -> Matrix e () a
forall e a b.
(Liftable e a b, CountableDimsN a b, FLN b a) =>
(a -> b) -> Matrix e a b
fromF ((() -> a) -> Matrix e () a)
-> (a -> () -> a) -> a -> Matrix e () a
forall (k :: Type -> Type -> Type) b c a.
Category k =>
k b c -> k a b -> k a c
. a -> () -> a
forall a b. a -> b -> a
const

-- iden Matrix

-- | iden matrix
iden ::
  (Num e, FLN a a, CountableN a) =>
  Matrix e a a
iden :: Matrix e a a
iden = Matrix e (Normalize a) (Normalize a) -> Matrix e a a
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M Matrix e (Normalize a) (Normalize a)
forall e cols.
(Num e, FL cols cols, Countable cols) =>
Matrix e cols cols
I.iden
{-# NOINLINE iden #-}

-- Matrix composition (MMM)

-- | Matrix composition. Equivalent to matrix-matrix multiplication.
--
--   This definition takes advantage of divide-and-conquer and fusion laws
-- from LAoP.
comp :: (Num e) => Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
comp :: Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
comp (M Matrix e (Normalize cr) (Normalize rows)
a) (M Matrix e (Normalize cols) (Normalize cr)
b) = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cr) (Normalize rows)
-> Matrix e (Normalize cols) (Normalize cr)
-> Matrix e (Normalize cols) (Normalize rows)
forall e cr rows cols.
Num e =>
Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
I.comp Matrix e (Normalize cr) (Normalize rows)
a Matrix e (Normalize cols) (Normalize cr)
b)
{-# NOINLINE comp #-}
{-# RULES
   "comp/iden1" forall m. comp m iden = m ;
   "comp/iden2" forall m. comp iden m = m
#-}

-- Scalar multiplication of matrices

infixl 7 .|
-- | Scalar multiplication of matrices.
(.|) :: Num e => e -> Matrix e cols rows -> Matrix e cols rows
.| :: e -> Matrix e cols rows -> Matrix e cols rows
(.|) e
e (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (e
e e
-> Matrix e (Normalize cols) (Normalize rows)
-> Matrix e (Normalize cols) (Normalize rows)
forall e cols rows.
Num e =>
e -> Matrix e cols rows -> Matrix e cols rows
I..| Matrix e (Normalize cols) (Normalize rows)
m)

-- Scalar division of matrices

infixl 7 ./
-- | Scalar multiplication of matrices.
(./) :: Fractional e => Matrix e cols rows -> e -> Matrix e cols rows
./ :: Matrix e cols rows -> e -> Matrix e cols rows
(./) (M Matrix e (Normalize cols) (Normalize rows)
m) e
e = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Normalize rows)
m Matrix e (Normalize cols) (Normalize rows)
-> e -> Matrix e (Normalize cols) (Normalize rows)
forall e cols rows.
Fractional e =>
Matrix e cols rows -> e -> Matrix e cols rows
I../ e
e)

-- | Biproduct first component projection
p1 ::
  ( Num e,
    CountableDimsN n m,
    FLN n m,
    FLN m m
  ) =>
  Matrix e (Either m n) m
p1 :: Matrix e (Either m n) m
p1 = Matrix e (Normalize (Either m n)) (Normalize m)
-> Matrix e (Either m n) m
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M Matrix e (Normalize (Either m n)) (Normalize m)
forall e n m.
(Num e, CountableDims n m, FL n m, FL m m) =>
Matrix e (Either m n) m
I.p1

-- | Biproduct second component projection
p2 ::
  ( Num e,
    CountableDimsN n m,
    FLN m n,
    FLN n n
  ) =>
  Matrix e (Either m n) n
p2 :: Matrix e (Either m n) n
p2 = Matrix e (Normalize (Either m n)) (Normalize n)
-> Matrix e (Either m n) n
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M Matrix e (Normalize (Either m n)) (Normalize n)
forall e n m.
(Num e, CountableDims n m, FL m n, FL n n) =>
Matrix e (Either m n) n
I.p2

-- Injections

-- | Biproduct first component injection
i1 ::
  ( Num e,
    CountableDimsN n m,
    FLN n m,
    FLN m m
  ) =>
  Matrix e m (Either m n)
i1 :: Matrix e m (Either m n)
i1 = Matrix e (Either m n) m -> Matrix e m (Either m n)
forall e cols rows. Matrix e cols rows -> Matrix e rows cols
tr Matrix e (Either m n) m
forall e n m.
(Num e, CountableDimsN n m, FLN n m, FLN m m) =>
Matrix e (Either m n) m
p1

-- | Biproduct second component injection
i2 ::
  ( Num e,
    CountableDimsN n m,
    FLN m n,
    FLN n n
  ) =>
  Matrix e n (Either m n)
i2 :: Matrix e n (Either m n)
i2 = Matrix e (Either m n) n -> Matrix e n (Either m n)
forall e cols rows. Matrix e cols rows -> Matrix e rows cols
tr Matrix e (Either m n) n
forall e n m.
(Num e, CountableDimsN n m, FLN m n, FLN n n) =>
Matrix e (Either m n) n
p2

-- Dimensions

-- | Obtain the number of rows.
--
--   NOTE: The 'KnownNat' constraint is needed in order to obtain the
-- dimensions in constant time. For a version that doesn't require the
-- constraint see 'rows''.
rows :: (CountableN rows) => Matrix e cols rows -> Int
rows :: Matrix e cols rows -> Int
rows (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> Int
forall e cols rows. Countable rows => Matrix e cols rows -> Int
I.rows Matrix e (Normalize cols) (Normalize rows)
m

-- | Obtain the number of rows in an inefficient manner, but without any
-- constraints.
--
-- For a more efficient version see 'rows'.
rows' :: Matrix e cols rows -> Int
rows' :: Matrix e cols rows -> Int
rows' (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> Int
forall e cols rows. Matrix e cols rows -> Int
I.rows' Matrix e (Normalize cols) (Normalize rows)
m

-- | Obtain the number of columns.
--
--   NOTE: The 'KnownNat' constraint is needed in order to obtain the
-- dimensions in constant time. For a version that doesn't require the
-- constraint see 'columns''.
columns :: (CountableN cols) => Matrix e cols rows -> Int
columns :: Matrix e cols rows -> Int
columns (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> Int
forall e cols rows. Countable cols => Matrix e cols rows -> Int
I.columns Matrix e (Normalize cols) (Normalize rows)
m

-- | Obtain the number of columns in an inefficient manner, but without any
-- constraints.
--
-- For a more efficient version see 'columns'.
columns' :: Matrix e cols rows -> Int
columns' :: Matrix e cols rows -> Int
columns' (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> Int
forall e cols rows. Matrix e cols rows -> Int
I.columns' Matrix e (Normalize cols) (Normalize rows)
m

-- Coproduct Bifunctor

infixl 5 -|-

-- | Matrix coproduct functor also known as matrix direct sum.
(-|-) ::
  ( Num e,
    CountableDimsN j k,
    FLN k k,
    FLN j k,
    FLN k j,
    FLN j j
  ) =>
  Matrix e n k ->
  Matrix e m j ->
  Matrix e (Either n m) (Either k j)
-|- :: Matrix e n k -> Matrix e m j -> Matrix e (Either n m) (Either k j)
(-|-) (M Matrix e (Normalize n) (Normalize k)
a) (M Matrix e (Normalize m) (Normalize j)
b) = Matrix e (Normalize (Either n m)) (Normalize (Either k j))
-> Matrix e (Either n m) (Either k j)
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize n) (Normalize k)
-> Matrix e (Normalize m) (Normalize j)
-> Matrix
     e
     (Either (Normalize n) (Normalize m))
     (Either (Normalize k) (Normalize j))
forall e n k m j.
(Num e, CountableDims j k, FL k k, FL j k, FL k j, FL j j) =>
Matrix e n k -> Matrix e m j -> Matrix e (Either n m) (Either k j)
(I.-|-) Matrix e (Normalize n) (Normalize k)
a Matrix e (Normalize m) (Normalize j)
b)

-- Khatri Rao Product and projections

-- | Khatri Rao product first component projection matrix.
fstM ::
  forall e m k .
  ( Num e,
    CountableDimsN m k,
    CountableN (m, k),
    FLN (m, k) m,
    TrivialP m k
  ) => Matrix e (m, k) m
fstM :: Matrix e (m, k) m
fstM = Matrix e (Normalize (m, k)) (Normalize m) -> Matrix e (m, k) m
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M ((Num e, CountableDims (Normalize k) (Normalize m),
 FL (Normalize (Normalize m, Normalize k)) (Normalize m),
 CountableN (Normalize m, Normalize k)) =>
Matrix e (Normalize (Normalize m, Normalize k)) (Normalize m)
forall e m k.
(Num e, CountableDims k m, FL (Normalize (m, k)) m,
 CountableN (m, k)) =>
Matrix e (Normalize (m, k)) m
I.fstM @e @(I.Normalize m) @(I.Normalize k))

-- | Khatri Rao product second component projection matrix.
sndM ::
    forall e m k.
    ( Num e,
      CountableDimsN k m,
      CountableN (m, k),
      FLN (m, k) k,
      TrivialP m k
    ) => Matrix e (m, k) k
sndM :: Matrix e (m, k) k
sndM = Matrix e (Normalize (m, k)) (Normalize k) -> Matrix e (m, k) k
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M ((Num e, CountableDims (Normalize k) (Normalize m),
 FL (Normalize (Normalize m, Normalize k)) (Normalize k),
 CountableN (Normalize m, Normalize k)) =>
Matrix e (Normalize (Normalize m, Normalize k)) (Normalize k)
forall e m k.
(Num e, CountableDims k m, FL (Normalize (m, k)) k,
 CountableN (m, k)) =>
Matrix e (Normalize (m, k)) k
I.sndM @e @(I.Normalize m) @(I.Normalize k))

-- | Khatri Rao Matrix product also known as matrix pairing.
--
--   NOTE: That this is not a true categorical product, see for instance:
--
-- @
--            | fstM . kr a b == a
-- kr a b ==> |
--            | sndM . kr a b == b
-- @
--
-- __Emphasis__ on the implication symbol.
kr ::
  forall e cols a b.
  ( Num e,
    CountableDimsN a b,
    CountableN (a, b),
    FLN (a, b) a,
    FLN (a, b) b,
    TrivialP a b
  ) => Matrix e cols a -> Matrix e cols b -> Matrix e cols (a, b)
kr :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (a, b)
kr Matrix e cols a
a Matrix e cols b
b =
  let fstM' :: Matrix e (a, b) a
fstM' = (Num e, CountableDimsN a b, CountableN (a, b), FLN (a, b) a,
 TrivialP a b) =>
Matrix e (a, b) a
forall e m k.
(Num e, CountableDimsN m k, CountableN (m, k), FLN (m, k) m,
 TrivialP m k) =>
Matrix e (m, k) m
fstM @e @a @b
      sndM' :: Matrix e (a, b) b
sndM' = (Num e, CountableDimsN b a, CountableN (a, b), FLN (a, b) b,
 TrivialP a b) =>
Matrix e (a, b) b
forall e m k.
(Num e, CountableDimsN k m, CountableN (m, k), FLN (m, k) k,
 TrivialP m k) =>
Matrix e (m, k) k
sndM @e @a @b
   in Matrix e a (a, b) -> Matrix e cols a -> Matrix e cols (a, b)
forall e cr rows cols.
Num e =>
Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
comp (Matrix e (a, b) a -> Matrix e a (a, b)
forall e cols rows. Matrix e cols rows -> Matrix e rows cols
tr Matrix e (a, b) a
fstM') Matrix e cols a
a Matrix e cols (a, b)
-> Matrix e cols (a, b) -> Matrix e cols (a, b)
forall a. Num a => a -> a -> a
* Matrix e b (a, b) -> Matrix e cols b -> Matrix e cols (a, b)
forall e cr rows cols.
Num e =>
Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
comp (Matrix e (a, b) b -> Matrix e b (a, b)
forall e cols rows. Matrix e cols rows -> Matrix e rows cols
tr Matrix e (a, b) b
sndM') Matrix e cols b
b

-- Product Bifunctor (Kronecker)

infixl 4 ><

-- | Matrix product functor also known as Kronecker product
(><) ::
  forall e m p n q.
  ( Num e,
    CountableDimsN m n,
    CountableDimsN p q,
    CountableDimsN (m, n) (p, q),
    FLN (m, n) m,
    FLN (m, n) n,
    FLN (p, q) p,
    FLN (p, q) q,
    TrivialP m n,
    TrivialP p q
  ) => Matrix e m p -> Matrix e n q -> Matrix e (m, n) (p, q)
>< :: Matrix e m p -> Matrix e n q -> Matrix e (m, n) (p, q)
(><) Matrix e m p
a Matrix e n q
b =
  let fstM' :: Matrix e (m, n) m
fstM' = (Num e, CountableDimsN m n, CountableN (m, n), FLN (m, n) m,
 TrivialP m n) =>
Matrix e (m, n) m
forall e m k.
(Num e, CountableDimsN m k, CountableN (m, k), FLN (m, k) m,
 TrivialP m k) =>
Matrix e (m, k) m
fstM @e @m @n
      sndM' :: Matrix e (m, n) n
sndM' = (Num e, CountableDimsN n m, CountableN (m, n), FLN (m, n) n,
 TrivialP m n) =>
Matrix e (m, n) n
forall e m k.
(Num e, CountableDimsN k m, CountableN (m, k), FLN (m, k) k,
 TrivialP m k) =>
Matrix e (m, k) k
sndM @e @m @n
   in Matrix e (m, n) p -> Matrix e (m, n) q -> Matrix e (m, n) (p, q)
forall e cols a b.
(Num e, CountableDimsN a b, CountableN (a, b), FLN (a, b) a,
 FLN (a, b) b, TrivialP a b) =>
Matrix e cols a -> Matrix e cols b -> Matrix e cols (a, b)
kr (Matrix e m p -> Matrix e (m, n) m -> Matrix e (m, n) p
forall e cr rows cols.
Num e =>
Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
comp Matrix e m p
a Matrix e (m, n) m
fstM') (Matrix e n q -> Matrix e (m, n) n -> Matrix e (m, n) q
forall e cr rows cols.
Num e =>
Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
comp Matrix e n q
b Matrix e (m, n) n
sndM')

-- Matrix abide Join Fork

-- | Matrix "abiding" followin the 'Join'-'Fork' abide law.
--
-- Law:
--
-- @
-- 'Join' ('Fork' a c) ('Fork' b d) == 'Fork' ('Join' a b) ('Join' c d)
-- @
abideJF :: Matrix e cols rows -> Matrix e cols rows
abideJF :: Matrix e cols rows -> Matrix e cols rows
abideJF (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Normalize rows)
-> Matrix e (Normalize cols) (Normalize rows)
forall e cols rows. Matrix e cols rows -> Matrix e cols rows
I.abideJF Matrix e (Normalize cols) (Normalize rows)
m)

-- Matrix abide Fork Join

-- | Matrix "abiding" followin the 'Fork'-'Join' abide law.
--
-- Law:
--
-- @
-- 'Fork' ('Join' a b) ('Join' c d) == 'Join' ('Fork' a c) ('Fork' b d)
-- @
abideFJ :: Matrix e cols rows -> Matrix e cols rows
abideFJ :: Matrix e cols rows -> Matrix e cols rows
abideFJ (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Normalize rows)
-> Matrix e (Normalize cols) (Normalize rows)
forall e cols rows. Matrix e cols rows -> Matrix e cols rows
I.abideFJ Matrix e (Normalize cols) (Normalize rows)
m)

-- Matrix transposition

-- | Matrix transposition.
tr :: Matrix e cols rows -> Matrix e rows cols
tr :: Matrix e cols rows -> Matrix e rows cols
tr (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize rows) (Normalize cols) -> Matrix e rows cols
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Normalize rows)
-> Matrix e (Normalize rows) (Normalize cols)
forall e cols rows. Matrix e cols rows -> Matrix e rows cols
I.tr Matrix e (Normalize cols) (Normalize rows)
m)

-- Selective 'select' operator

-- | Selective functors 'select' operator equivalent inspired by the
-- ArrowMonad solution presented in the paper.
selectM ::
       ( Num e,
         FLN b b,
         CountableN b
       ) => Matrix e cols (Either a b) -> Matrix e a b -> Matrix e cols b
selectM :: Matrix e cols (Either a b) -> Matrix e a b -> Matrix e cols b
selectM (M Matrix e (Normalize cols) (Normalize (Either a b))
m) (M Matrix e (Normalize a) (Normalize b)
y) = Matrix e (Normalize cols) (Normalize b) -> Matrix e cols b
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M (Matrix e (Normalize cols) (Either (Normalize a) (Normalize b))
-> Matrix e (Normalize a) (Normalize b)
-> Matrix e (Normalize cols) (Normalize b)
forall e b cols a.
(Num e, FL b b, Countable b) =>
Matrix e cols (Either a b) -> Matrix e a b -> Matrix e cols b
I.select Matrix e (Normalize cols) (Either (Normalize a) (Normalize b))
Matrix e (Normalize cols) (Normalize (Either a b))
m Matrix e (Normalize a) (Normalize b)
y)

-- McCarthy's Conditional

-- | McCarthy's Conditional expresses probabilistic choice.
cond ::
     ( Trivial a,
       Trivial2 a,
       Trivial3 a,
       CountableN a,
       FLN () a,
       FLN a (),
       FLN a a,
       Liftable e a Bool
     )
     =>
     (a -> Bool) -> Matrix e a b -> Matrix e a b -> Matrix e a b
cond :: (a -> Bool) -> Matrix e a b -> Matrix e a b -> Matrix e a b
cond a -> Bool
p (M Matrix e (Normalize a) (Normalize b)
a) (M Matrix e (Normalize a) (Normalize b)
b) = Matrix e (Normalize a) (Normalize b) -> Matrix e a b
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M ((a -> Bool)
-> Matrix e (Normalize (Normalize a)) (Normalize b)
-> Matrix e (Normalize (Normalize a)) (Normalize b)
-> Matrix e (Normalize (Normalize a)) (Normalize b)
forall cols a e rows.
(Trivial cols, Countable cols, FL () cols, FL cols (),
 FL cols cols, Bounded a, Enum a, Num e, Ord e) =>
(a -> Bool)
-> Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
I.cond a -> Bool
p Matrix e (Normalize a) (Normalize b)
Matrix e (Normalize (Normalize a)) (Normalize b)
a Matrix e (Normalize a) (Normalize b)
Matrix e (Normalize (Normalize a)) (Normalize b)
b)

-- Pretty print

-- | Matrix pretty printer
pretty :: (CountableDimsN cols rows, Show e) => Matrix e cols rows -> String
pretty :: Matrix e cols rows -> String
pretty (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> String
forall cols rows e.
(CountableDims cols rows, Show e) =>
Matrix e cols rows -> String
I.pretty Matrix e (Normalize cols) (Normalize rows)
m

-- | Matrix pretty printer
prettyPrint :: (CountableDimsN cols rows, Show e) => Matrix e cols rows -> IO ()
prettyPrint :: Matrix e cols rows -> IO ()
prettyPrint (M Matrix e (Normalize cols) (Normalize rows)
m) = Matrix e (Normalize cols) (Normalize rows) -> IO ()
forall cols rows e.
(CountableDims cols rows, Show e) =>
Matrix e cols rows -> IO ()
I.prettyPrint Matrix e (Normalize cols) (Normalize rows)
m

-- | Zip two matrices with a given binary function
zipWithM :: (e -> f -> g) -> Matrix e a b -> Matrix f a b -> Matrix g a b
zipWithM :: (e -> f -> g) -> Matrix e a b -> Matrix f a b -> Matrix g a b
zipWithM e -> f -> g
f (M Matrix e (Normalize a) (Normalize b)
a) (M Matrix f (Normalize a) (Normalize b)
b) = Matrix g (Normalize a) (Normalize b) -> Matrix g a b
forall e cols rows.
Matrix e (Normalize cols) (Normalize rows) -> Matrix e cols rows
M ((e -> f -> g)
-> Matrix e (Normalize a) (Normalize b)
-> Matrix f (Normalize a) (Normalize b)
-> Matrix g (Normalize a) (Normalize b)
forall e f g cols rows.
(e -> f -> g)
-> Matrix e cols rows -> Matrix f cols rows -> Matrix g cols rows
I.zipWithM e -> f -> g
f Matrix e (Normalize a) (Normalize b)
a Matrix f (Normalize a) (Normalize b)
b)