@@ -13,22 +13,34 @@
13{-# LANGUAGE TypeOperators #-}
13{-# LANGUAGE TypeOperators #-}
14{-# LANGUAGE UndecidableInstances #-}
14{-# LANGUAGE UndecidableInstances #-}
16+-----------------------------------------------------------------------------
18+-- Module : Matrix.Type
19+-- Copyright : (c) Armando Santos 2019-2020
20+-- Maintainer : armandoifsantos@gmail.com
21+-- Stability : experimental
23+-- The LAoP discipline generalises relations and functions treating them as
24+-- Boolean matrices and in turn consider these as arrows.
26+-- __LAoP__ is a library for algebraic (inductive) construction and manipulation of matrices
27+-- in Haskell. See <https://github.com/bolt12/master-thesis my Msc Thesis> for the
28+-- motivation behind the library, the underlying theory, and implementation details.
30+-- This module offers many of the combinators mentioned in the work of
31+-- Macedo (2012) and Oliveira (2012).
33+-----------------------------------------------------------------------------
16module Matrix.Type
35module Matrix.Type
17− ( -- | LAoP (Linear Algebra of Programming) Inductive Matrix definition.
19− -- LAoP generalises relations and functions treating them as
20− -- Boolean matrices and in turn consider these as arrows.
21− -- This library offers many of the combinators mentioned in the work of
22− -- Macedo (2012) and Oliveira (2012).
24− -- This definition makes use of the fact that 'Void' is
36+ ( -- | This definition makes use of the fact that 'Void' is
25− -- isomorphic to 0 and '()' to 1 and captures matrix
37+ -- isomorphic to 0 and '()' to 1 and captures matrix
26− -- dimensions as stacks of 'Either's.
38+ -- dimensions as stacks of 'Either's.
28− -- There exists two type families that make it easier to write
40+ -- There exists two type families that make it easier to write
29− -- matrix dimensions: 'FromNat' and 'Count'. This approach
41+ -- matrix dimensions: 'FromNat' and 'Count'. This approach
30− -- leads to a very straightforward implementation
42+ -- leads to a very straightforward implementation
31− -- of LAoP combinators.
43+ -- of LAoP combinators.
33 -- * Type safe matrix representation
45 -- * Type safe matrix representation
34 Matrix (..),
46 Matrix (..),
@@ -95,9 +107,7 @@ module Matrix.Type
95 -- | Note that given the restrictions imposed it is not possible to
107 -- | Note that given the restrictions imposed it is not possible to
96 -- implement the standard type classes present in standard Haskell.
108 -- implement the standard type classes present in standard Haskell.
97 -- *** Matrix pairing projections
109 -- *** Matrix pairing projections
103 -- *** Matrix pairing
113 -- *** Matrix pairing
@@ -127,8 +137,9 @@ import Data.List
127import Data.Proxy
137import Data.Proxy
128import Data.Void
138import Data.Void
129import GHC.TypeLits
139import GHC.TypeLits
131−-- | Matrix data type
142+-- | LAoP (Linear Algebra of Programming) Inductive Matrix definition.
132data Matrix e cols rows where
143data Matrix e cols rows where
133 Empty :: Matrix e Void Void
144 Empty :: Matrix e Void Void
134 One :: e -> Matrix e () ()
145 One :: e -> Matrix e () ()
@@ -137,17 +148,24 @@ data Matrix e cols rows where
138deriving instance (Show e) => Show (Matrix e cols rows)
149deriving instance (Show e) => Show (Matrix e cols rows)
140−-- | Type family that computes the cardinality of a given type dimension
151+-- | Type family that computes the cardinality of a given type dimension.
152+-- It can also count the cardinality of custom types that implement the
153+-- 'Generic' instance.
141type family Count (d :: Type) where
154type family Count (d :: Type) where
145 Count (Natural n) = n
155 Count (Natural n) = n
146 Count (Either a b) = (+) (Count a) (Count b)
156 Count (Either a b) = (+) (Count a) (Count b)
147 Count (a, b) = (*) (Count a) (Count b)
157 Count (a, b) = (*) (Count a) (Count b)
148 Count (a -> b) = (^) (Count b) (Count a)
158 Count (a -> b) = (^) (Count b) (Count a)
160+ Count (M1 _ _ f p) = Count (f p)
161+ Count (K1 _ _ _) = 1
164+ Count ((:*:) a b p) = Count (a p) * Count (b p)
165+ Count ((:+:) a b p) = Count (a p) + Count (b p)
166+ Count d = Count (Rep d R)
150−-- | Type family that computes of a given type dimension from a fiven natural
168+-- | Type family that computes of a given type dimension from a given natural
151type family FromNat (n :: Nat) where
169type family FromNat (n :: Nat) where
152 FromNat 0 = Void
170 FromNat 0 = Void
153 FromNat 1 = ()
171 FromNat 1 = ()
@@ -199,47 +217,65 @@ instance Num e => Num (Matrix e cols rows) where
200-- Primitives
218-- Primitives
220+-- | Empty matrix constructor
202empty :: Matrix e Void Void
221empty :: Matrix e Void Void
203empty = Empty
222empty = Empty
224+-- | Unit matrix constructor
205one :: e -> Matrix e () ()
225one :: e -> Matrix e () ()
228+-- | Matrix 'Junc' constructor
208junc :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
229junc :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
209junc = Junc
230junc = Junc
211infixl 3 |||
232infixl 3 |||
234+-- | Matrix 'Junc' constructor
212(|||) :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
235(|||) :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
213(|||) = Junc
236(|||) = Junc
238+-- | Matrix 'Split' constructor
215split :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
239split :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
216split = Split
240split = Split
218infixl 2 ===
242infixl 2 ===
244+-- | Matrix 'Split' constructor
219(===) :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
245(===) :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
220(===) = Split
246(===) = Split
222-- Construction
248-- Construction
250+-- | Type class for defining the 'fromList' conversion function.
251+-- Given that it is not possible to branch on types at the term level type
252+-- classes are needed bery much like an inductive definition but on types.
224class FromLists e cols rows where
253class FromLists e cols rows where
254+ -- | Build a matrix out of a list of list of elements. Throws a runtime
255+ -- error if the dimensions do not match.
225 fromLists :: [[e]] -> Matrix e cols rows
256 fromLists :: [[e]] -> Matrix e cols rows
227instance FromLists e Void Void where
259instance FromLists e Void Void where
228 fromLists [] = Empty
260 fromLists [] = Empty
229 fromLists _ = error "Wrong dimensions"
261 fromLists _ = error "Wrong dimensions"
231instance {-# OVERLAPPING #-} FromLists e () () where
264instance {-# OVERLAPPING #-} FromLists e () () where
232 fromLists [[e]] = One e
265 fromLists [[e]] = One e
233 fromLists _ = error "Wrong dimensions"
266 fromLists _ = error "Wrong dimensions"
268+-- | Row vector matrix definition
235instance (FromLists e cols ()) => FromLists e (Either () cols) () where
269instance (FromLists e cols ()) => FromLists e (Either () cols) () where
236 fromLists [h : t] = Junc (One h) (fromLists [t])
270 fromLists [h : t] = Junc (One h) (fromLists [t])
237 fromLists _ = error "Wrong dimensions"
271 fromLists _ = error "Wrong dimensions"
273+-- | Column vector matrix definition
239instance (FromLists e () rows) => FromLists e () (Either () rows) where
274instance (FromLists e () rows) => FromLists e () (Either () rows) where
240 fromLists ([h] : t) = Split (One h) (fromLists t)
275 fromLists ([h] : t) = Split (One h) (fromLists t)
241 fromLists _ = error "Wrong dimensions"
276 fromLists _ = error "Wrong dimensions"
278+-- | Arbitrary matrix definition
243instance {-# OVERLAPPABLE #-} (FromLists e cols c, FromLists e cols d) => FromLists e cols (Either c d) where
279instance {-# OVERLAPPABLE #-} (FromLists e cols c, FromLists e cols d) => FromLists e cols (Either c d) where
244 fromLists (h : t) =
280 fromLists (h : t) =
245 let lh = length h
281 let lh = length h
@@ -248,6 +284,8 @@ instance {-# OVERLAPPABLE #-} (FromLists e cols c, FromLists e cols d) => FromLi
248 then Split (fromLists [h]) (fromLists t)
284 then Split (fromLists [h]) (fromLists t)
249 else error "Not all rows have the same length"
285 else error "Not all rows have the same length"
287+-- | Matrix builder function. Constructs a matrix provided with
288+-- a construction function.
251matrixBuilder ::
289matrixBuilder ::
252 forall e cols rows.
290 forall e cols rows.
253 ( FromLists e cols rows,
291 ( FromLists e cols rows,
@@ -262,12 +300,17 @@ matrixBuilder f =
262 positions = [(a, b) | a <- [0 .. (r - 1)], b <- [0 .. (c - 1)]]
300 positions = [(a, b) | a <- [0 .. (r - 1)], b <- [0 .. (c - 1)]]
263 in fromLists . map (map f) . groupBy (\(x, _) (w, _) -> x == w) $ positions
301 in fromLists . map (map f) . groupBy (\(x, _) (w, _) -> x == w) $ positions
303+-- | Constructs a column vector matrix
265col :: (FromLists e () rows) => [e] -> Matrix e () rows
304col :: (FromLists e () rows) => [e] -> Matrix e () rows
266col = fromLists . map (: [])
305col = fromLists . map (: [])
307+-- | Constructs a row vector matrix
268row :: (FromLists e cols ()) => [e] -> Matrix e cols ()
308row :: (FromLists e cols ()) => [e] -> Matrix e cols ()
269row = fromLists . (: [])
309row = fromLists . (: [])
311+-- | Lifts functions to matrices with arbitrary dimensions.
312+-- NOTE: Be careful to not ask for a matrix bigger than the cardinality of
313+-- types @a@ or @b@ allows.
272 forall a b cols rows e.
315 forall a b cols rows e.
273 ( Bounded a,
316 ( Bounded a,
@@ -302,6 +345,8 @@ fromF f =
302 buildList [] _ = []
345 buildList [] _ = []
303 buildList l r = take r l : buildList (drop r l) r
346 buildList l r = take r l : buildList (drop r l) r
348+-- | Lifts functions to matrices with dimensions matching @a@ and @b@
306 forall a b e.
351 forall a b e.
307 ( Bounded a,
352 ( Bounded a,
@@ -338,32 +383,40 @@ fromF' f =
339-- Conversion
384-- Conversion
386+-- | Converts a matrix to a list of lists of elements.
341toLists :: Matrix e cols rows -> [[e]]
387toLists :: Matrix e cols rows -> [[e]]
342toLists Empty = []
388toLists Empty = []
343toLists (One e) = [[e]]
389toLists (One e) = [[e]]
344toLists (Split l r) = toLists l ++ toLists r
390toLists (Split l r) = toLists l ++ toLists r
345toLists (Junc l r) = zipWith (++) (toLists l) (toLists r)
391toLists (Junc l r) = zipWith (++) (toLists l) (toLists r)
393+-- | Converts a matrix to a list of elements.
347toList :: Matrix e cols rows -> [e]
394toList :: Matrix e cols rows -> [e]
348toList = concat . toLists
395toList = concat . toLists
350-- Zeros Matrix
397-- Zeros Matrix
399+-- | The zero matrix. A matrix wholly filled with zeros.
352zeros :: (Num e, FromLists e cols rows, KnownNat (Count cols), KnownNat (Count rows)) => Matrix e cols rows
400zeros :: (Num e, FromLists e cols rows, KnownNat (Count cols), KnownNat (Count rows)) => Matrix e cols rows
353zeros = matrixBuilder (const 0)
401zeros = matrixBuilder (const 0)
355-- Ones Matrix
403-- Ones Matrix
405+-- | The ones matrix. A matrix wholly filled with ones.
406+-- Also known as T (Top) matrix.
357ones :: (Num e, FromLists e cols rows, KnownNat (Count cols), KnownNat (Count rows)) => Matrix e cols rows
407ones :: (Num e, FromLists e cols rows, KnownNat (Count cols), KnownNat (Count rows)) => Matrix e cols rows
358ones = matrixBuilder (const 1)
408ones = matrixBuilder (const 1)
360-- Const Matrix
410-- Const Matrix
412+-- | The constant matrix constructor. A matrix wholly filled with a given
362constant :: (Num e, FromLists e cols rows, KnownNat (Count cols), KnownNat (Count rows)) => e -> Matrix e cols rows
414constant :: (Num e, FromLists e cols rows, KnownNat (Count cols), KnownNat (Count rows)) => e -> Matrix e cols rows
363constant e = matrixBuilder (const e)
415constant e = matrixBuilder (const e)
365-- Bang Matrix
417-- Bang Matrix
419+-- | The T (Top) row vector matrix.
367bang :: forall e cols. (Num e, Enum e, FromLists e cols (), KnownNat (Count cols)) => Matrix e cols ()
420bang :: forall e cols. (Num e, Enum e, FromLists e cols (), KnownNat (Count cols)) => Matrix e cols ()
369 let c = fromInteger $ natVal (Proxy :: Proxy (Count cols))
422 let c = fromInteger $ natVal (Proxy :: Proxy (Count cols))
@@ -371,11 +424,15 @@ bang =
372-- Identity Matrix
425-- Identity Matrix
427+-- | Identity matrix.
374identity :: (Num e, FromLists e cols cols, KnownNat (Count cols)) => Matrix e cols cols
428identity :: (Num e, FromLists e cols cols, KnownNat (Count cols)) => Matrix e cols cols
375identity = matrixBuilder (bool 0 1 . uncurry (==))
429identity = matrixBuilder (bool 0 1 . uncurry (==))
377-- Matrix composition (MMM)
431-- Matrix composition (MMM)
433+-- | Matrix composition. Equivalent to matrix-matrix multiplication.
434+-- This definition takes advantage of divide-and-conquer and fusion laws
379comp :: (Num e) => Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
436comp :: (Num e) => Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
380comp Empty Empty = Empty
437comp Empty Empty = Empty
381comp (One a) (One b) = One (a * b)
438comp (One a) (One b) = One (a * b)
@@ -385,12 +442,14 @@ comp c (Junc a b) = Junc (comp c a) (comp c b) -- Junc fusion law
386-- Projections
443-- Projections
445+-- | Biproduct first component projection
388p1 :: forall e m n. (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e n m, FromLists e m m) => Matrix e (Either m n) m
446p1 :: forall e m n. (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e n m, FromLists e m m) => Matrix e (Either m n) m
390 let iden = identity :: Matrix e m m
448 let iden = identity :: Matrix e m m
391 zero = zeros :: Matrix e n m
449 zero = zeros :: Matrix e n m
392 in junc iden zero
450 in junc iden zero
452+-- | Biproduct second component projection
394p2 :: forall e m n. (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e m n, FromLists e n n) => Matrix e (Either m n) n
453p2 :: forall e m n. (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e m n, FromLists e n n) => Matrix e (Either m n) n
396 let iden = identity :: Matrix e n n
455 let iden = identity :: Matrix e n n
@@ -399,17 +458,29 @@ p2 =
400-- Injections
459-- Injections
461+-- | Biproduct first component injection
402i1 :: (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e n m, FromLists e m m) => Matrix e m (Either m n)
462i1 :: (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e n m, FromLists e m m) => Matrix e m (Either m n)
403i1 = tr p1
463i1 = tr p1
465+-- | Biproduct second component injection
405i2 :: (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e m n, FromLists e n n) => Matrix e n (Either m n)
466i2 :: (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e m n, FromLists e n n) => Matrix e n (Either m n)
406i2 = tr p2
467i2 = tr p2
408-- Dimensions
469-- Dimensions
471+-- | Obtain the number of rows.
472+-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
473+-- dimensions in constant time.
474+-- TODO: A 'rows' function that does not need the 'KnownNat' constraint in
475+-- exchange for performance.
410rows :: forall e cols rows. (KnownNat (Count rows)) => Matrix e cols rows -> Int
476rows :: forall e cols rows. (KnownNat (Count rows)) => Matrix e cols rows -> Int
411rows _ = fromInteger $ natVal (Proxy :: Proxy (Count rows))
477rows _ = fromInteger $ natVal (Proxy :: Proxy (Count rows))
479+-- | Obtain the number of columns.
480+-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
481+-- dimensions in constant time.
482+-- TODO: A 'columns' function that does not need the 'KnownNat' constraint in
483+-- exchange for performance.
413columns :: forall e cols rows. (KnownNat (Count cols)) => Matrix e cols rows -> Int
484columns :: forall e cols rows. (KnownNat (Count cols)) => Matrix e cols rows -> Int
414columns _ = fromInteger $ natVal (Proxy :: Proxy (Count cols))
485columns _ = fromInteger $ natVal (Proxy :: Proxy (Count cols))
@@ -417,6 +488,7 @@ columns _ = fromInteger $ natVal (Proxy :: Proxy (Count cols))
418infixl 5 -|-
489infixl 5 -|-
491+-- | Matrix coproduct functor also known as matrix direct sum.
421 forall e n k m j.
493 forall e n k m j.
@@ -434,51 +506,57 @@ infixl 5 -|-
435-- Khatri Rao Product and projections
507-- Khatri Rao Product and projections
437−class KhatriP1 e m k where
509+-- | Khatri Rao product first component projection matrix.
438− kp1 :: Matrix e (Normalize (m, k)) m
510+kp1 ::
440−instance KhatriP1 e Void k where
445 KnownNat (Count k),
513 KnownNat (Count k),
446 FromLists e (FromNat (Count m * Count k)) m,
514 FromLists e (FromNat (Count m * Count k)) m,
447 KnownNat (Count m),
515 KnownNat (Count m),
448 KnownNat (Count (Normalize (m, k)))
516 KnownNat (Count (Normalize (m, k)))
449− ) =>
517+ ) => Matrix e (Normalize (m, k)) m
450− KhatriP1 e m k
518+kp1 = matrixBuilder f
452− kp1 = matrixBuilder f
454− offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
520+ offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
455− f (x, y)
521+ f (x, y)
456− | y >= (x * offset) && y <= (x * offset + offset - 1) = 1
522+ | y >= (x * offset) && y <= (x * offset + offset - 1) = 1
457− | otherwise = 0
523+ | otherwise = 0
459−class KhatriP2 e m k where
525+-- | Khatri Rao product second component projection matrix.
460− kp2 :: Matrix e (Normalize (m, k)) k
526+kp2 ::
462−instance KhatriP2 e m Void where
466− ( Num e,
528+ ( Num e,
467− KnownNat (Count k),
529+ KnownNat (Count k),
468− FromLists e (FromNat (Count m * Count k)) k,
530+ FromLists e (FromNat (Count m * Count k)) k,
469− KnownNat (Count m),
531+ KnownNat (Count m),
470− KnownNat (Count (Normalize (m, k)))
532+ KnownNat (Count (Normalize (m, k)))
471− ) =>
533+ ) => Matrix e (Normalize (m, k)) k
472− KhatriP2 e m k
534+kp2 = matrixBuilder f
474− kp2 = matrixBuilder f
476− offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
536+ offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
477− f (x, y)
537+ f (x, y)
478− | x == y || mod (y - x) offset == 0 = 1
538+ | x == y || mod (y - x) offset == 0 = 1
479− | otherwise = 0
539+ | otherwise = 0
541+-- | Khatri Rao Matrix product also known as matrix pairing.
542+-- NOTE: That this is not a true categorical product, see for instance:
545+-- | kp1 `comp` khatri a b == a
547+-- | kp2 `comp` khatri a b == b
550+-- __Emphasis__ on the implication symbol.
556+ KnownNat (Count (Normalize (a, b))),
557+ FromLists e (Normalize (a, b)) a,
558+ FromLists e (Normalize (a, b)) b
481−khatri :: forall e cols a b. (Num e, KhatriP1 e a b, KhatriP2 e a b) => Matrix e cols a -> Matrix e cols b -> Matrix e cols (Normalize (a, b))
559+ ) => Matrix e cols a -> Matrix e cols b -> Matrix e cols (Normalize (a, b))
482khatri a b =
560khatri a b =
483 let kp1' = kp1 @e @a @b
561 let kp1' = kp1 @e @a @b
484 kp2' = kp2 @e @a @b
562 kp2' = kp2 @e @a @b
@@ -488,7 +566,22 @@ khatri a b =
489infixl 4 ><
567infixl 4 ><
569+-- | Matrix product functor also known as kronecker product
577+ KnownNat (Count (Normalize (m, n))),
578+ FromLists e (Normalize (m, n)) m,
579+ FromLists e (Normalize (m, n)) n,
580+ KnownNat (Count (Normalize (p, q))),
581+ FromLists e (Normalize (p, q)) p,
582+ FromLists e (Normalize (p, q)) q
491−(><) :: forall e m p n q. (Num e, KhatriP1 e m n, KhatriP2 e m n, KhatriP1 e p q, KhatriP2 e p q) => Matrix e m p -> Matrix e n q -> Matrix e (Normalize (m, n)) (Normalize (p, q))
584+ => Matrix e m p -> Matrix e n q -> Matrix e (Normalize (m, n)) (Normalize (p, q))
492(><) a b =
585(><) a b =
493 let kp1' = kp1 @e @m @n
586 let kp1' = kp1 @e @m @n
494 kp2' = kp2 @e @m @n
587 kp2' = kp2 @e @m @n
@@ -496,6 +589,11 @@ infixl 4 ><
497-- Matrix abide Junc Split
590-- Matrix abide Junc Split
592+-- | Matrix "abiding" followin the 'Junc'-'Split' abide law.
595+-- 'Junc' ('Split' a c) ('Split' b d) == 'Split' ('Junc' a b) ('Junc' c d)
499abideJS :: Matrix e cols rows -> Matrix e cols rows
597abideJS :: Matrix e cols rows -> Matrix e cols rows
500abideJS (Junc (Split a c) (Split b d)) = Split (Junc (abideJS a) (abideJS b)) (Junc (abideJS c) (abideJS d)) -- Junc-Split abide law
598abideJS (Junc (Split a c) (Split b d)) = Split (Junc (abideJS a) (abideJS b)) (Junc (abideJS c) (abideJS d)) -- Junc-Split abide law
501abideJS Empty = Empty
599abideJS Empty = Empty
@@ -505,6 +603,11 @@ abideJS (Split a b) = Split (abideJS a) (abideJS b)
506-- Matrix abide Split Junc
604-- Matrix abide Split Junc
606+-- | Matrix "abiding" followin the 'Split'-'Junc' abide law.
609+-- 'Split' ('Junc' a b) ('Junc' c d) == 'Junc' ('Split' a c) ('Split' b d)
508abideSJ :: Matrix e cols rows -> Matrix e cols rows
611abideSJ :: Matrix e cols rows -> Matrix e cols rows
509abideSJ (Split (Junc a b) (Junc c d)) = Junc (Split (abideSJ a) (abideSJ c)) (Split (abideSJ b) (abideSJ d)) -- Split-Junc abide law
612abideSJ (Split (Junc a b) (Junc c d)) = Junc (Split (abideSJ a) (abideSJ c)) (Split (abideSJ b) (abideSJ d)) -- Split-Junc abide law
510abideSJ Empty = Empty
613abideSJ Empty = Empty
@@ -514,6 +617,7 @@ abideSJ (Split a b) = Split (abideSJ a) (abideSJ b)
515-- Matrix transposition
618-- Matrix transposition
620+-- | Matrix transposition.
517tr :: Matrix e cols rows -> Matrix e rows cols
621tr :: Matrix e cols rows -> Matrix e rows cols
518tr Empty = Empty
622tr Empty = Empty
519tr (One e) = One e
623tr (One e) = One e
@@ -522,6 +626,8 @@ tr (Split a b) = Junc (tr a) (tr b)
523-- Selective 'select' operator
627-- Selective 'select' operator
629+-- | Selective functors 'select' operator equivalent inspired by the
630+-- ArrowMonad solution presented in the paper.
525select :: (Bounded a1, Bounded b, Enum a1, Enum b, Num e, Ord e,
631select :: (Bounded a1, Bounded b, Enum a1, Enum b, Num e, Ord e,
526 KnownNat (Count a2), KnownNat (Count rows), FromLists e rows a2,
632 KnownNat (Count a2), KnownNat (Count rows), FromLists e rows a2,
527 FromLists e rows rows, Eq b) =>
633 FromLists e rows rows, Eq b) =>
@@ -532,13 +638,13 @@ select m y =
533-- McCarthy's Conditional
639-- McCarthy's Conditional
641+-- | McCarthy's Conditional expresses probabilistic choice.
536 ( cols ~ FromNat (Count cols),
643 ( cols ~ FromNat (Count cols),
537 KnownNat (Count cols),
644 KnownNat (Count cols),
538 FromLists e () cols,
645 FromLists e () cols,
539 FromLists e cols (),
646 FromLists e cols (),
540 FromLists e cols cols,
647 FromLists e cols cols,
542 Bounded a,
648 Bounded a,
@@ -554,7 +660,6 @@ grd ::
554 FromLists e () q,
660 FromLists e () q,
555 FromLists e q (),
661 FromLists e q (),
556 FromLists e q q,
662 FromLists e q q,
558 Bounded a,
663 Bounded a,
@@ -571,7 +676,6 @@ corr ::
571 FromLists e () q,
676 FromLists e () q,
572 FromLists e q (),
677 FromLists e q (),
573 FromLists e q q,
678 FromLists e q q,
575 Bounded a,
679 Bounded a,
@@ -602,6 +706,7 @@ prettyAux (h : t) l = "│ " ++ fill (unwords $ map show h) ++ " │\n" ++
602 widest = maximum $ fmap length v
706 widest = maximum $ fmap length v
603 fill str = replicate (widest - length str - 2) ' ' ++ str
707 fill str = replicate (widest - length str - 2) ' ' ++ str
709+-- | Matrix pretty printer
605pretty :: (KnownNat (Count cols), Show e) => Matrix e cols rows -> String
710pretty :: (KnownNat (Count cols), Show e) => Matrix e cols rows -> String
606pretty m = "┌ " ++ unwords (replicate (columns m) blank) ++ " ┐\n" ++
711pretty m = "┌ " ++ unwords (replicate (columns m) blank) ++ " ┐\n" ++
607 prettyAux (toLists m) (toLists m) ++
712 prettyAux (toLists m) (toLists m) ++
@@ -612,5 +717,6 @@ pretty m = "┌ " ++ unwords (replicate (columns m) blank) ++ " ┐\n" ++
612 fill str = replicate (widest - length str) ' ' ++ str
717 fill str = replicate (widest - length str) ' ' ++ str
613 blank = fill ""
718 blank = fill ""
720+-- | Matrix pretty printer
615prettyPrint :: (KnownNat (Count cols), Show e) => Matrix e cols rows -> IO ()
721prettyPrint :: (KnownNat (Count cols), Show e) => Matrix e cols rows -> IO ()
616prettyPrint = putStrLn . pretty
722prettyPrint = putStrLn . pretty