on d2fbcb5 help sign in
src/LAoP/Matrix/Alternative.hsnew file+954
since splitsnapshots
unifiedsplit
@@ -0,0 +1,954 @@
1+{-# LANGUAGE TypeApplications #-}
2+{-# LANGUAGE LambdaCase #-}
3+{-# LANGUAGE StrictData #-}
4+{-# LANGUAGE TypeFamilyDependencies #-}
5+{-# LANGUAGE ConstraintKinds #-}
6+{-# LANGUAGE AllowAmbiguousTypes #-}
7+{-# LANGUAGE DataKinds #-}
8+{-# LANGUAGE FlexibleContexts #-}
9+{-# LANGUAGE FlexibleInstances #-}
10+{-# LANGUAGE GADTs #-}
11+{-# LANGUAGE InstanceSigs #-}
12+{-# LANGUAGE MultiParamTypeClasses #-}
13+{-# LANGUAGE NoStarIsType #-}
14+{-# LANGUAGE ScopedTypeVariables #-}
15+{-# LANGUAGE StandaloneDeriving #-}
16+{-# LANGUAGE TypeOperators #-}
17+{-# LANGUAGE UndecidableInstances #-}
18+
19+-----------------------------------------------------------------------------
20+-- |
21+-- Module : LAoP.Matrix.Internal
22+-- Copyright : (c) Armando Santos 2019-2020
23+-- Maintainer : armandoifsantos@gmail.com
24+-- Stability : experimental
25+--
26+-- The LAoP discipline generalises relations and functions treating them as
27+-- Boolean matrices and in turn consider these as arrows.
28+--
29+-- __LAoP__ is a library for algebraic (inductive) construction and manipulation of matrices
30+-- in Haskell. See <https://github.com/bolt12/master-thesis my Msc Thesis> for the
31+-- motivation behind the library, the underlying theory, and implementation details.
32+--
33+-- This module offers many of the combinators mentioned in the work of
34+-- Macedo (2012) and Oliveira (2012).
35+--
36+-- This is an Internal module and it is no supposed to be imported.
37+--
38+-----------------------------------------------------------------------------
39+
40+module LAoP.Matrix.Alternative
41+ ( -- | This definition makes use of the fact that 'Void' is
42+ -- isomorphic to 0 and '()' to 1 and captures matrix
43+ -- dimensions as stacks of 'Either's.
44+ --
45+ -- There exists two type families that make it easier to write
46+ -- matrix dimensions: 'FromNat' and 'Count'. This approach
47+ -- leads to a very straightforward implementation
48+ -- of LAoP combinators.
49+
50+ -- * Type safe matrix representation
51+ Matrix (..),
52+
53+ -- * Primitives
54+ empty,
55+ one,
56+ join,
57+ fork,
58+
59+ -- * Auxiliary type families
60+ FromNat,
61+ Count,
62+ Normalize,
63+
64+ -- * Matrix construction and conversion
65+ FromLists,
66+ fromLists,
67+ toLists,
68+ toList,
69+ matrixBuilder,
70+ matrixBuilderN,
71+ rowL,
72+ rowN,
73+ colL,
74+ colN,
75+ zeros,
76+ ones,
77+ bang,
78+ point,
79+ constant,
80+
81+ -- * Misc
82+ -- ** Get dimensions
83+ columns,
84+ rows,
85+
86+ -- ** Matrix Transposition
87+ tr,
88+
89+ -- ** Scalar multiplication/division of matrices
90+ (.|),
91+ (./),
92+
93+ -- ** Selective operator
94+ select,
95+ branch,
96+
97+ -- ** McCarthy's Conditional
98+ -- cond,
99+
100+ -- ** Matrix "abiding"
101+ abideJF,
102+ abideFJ,
103+
104+ -- ** Zip matrices
105+ zipWithM,
106+
107+ -- * Biproduct approach
108+ -- ** Fork
109+ (===),
110+ -- *** Projections
111+ p1,
112+ p2,
113+ -- ** Join
114+ (|||),
115+ -- *** Injections
116+ i1,
117+ i2,
118+ -- ** Bifunctors
119+ (-|-),
120+ (><),
121+
122+ -- ** Applicative matrix combinators
123+
124+ -- | Note that given the restrictions imposed it is not possible to
125+ -- implement the standard type classes present in standard Haskell.
126+ -- *** Matrix pairing projections
127+ fstM,
128+ sndM,
129+
130+ -- *** Matrix pairing
131+ kr,
132+
133+ -- * Matrix composition and lifting
134+
135+ -- ** Arrow matrix combinators
136+
137+ -- | Note that given the restrictions imposed it is not possible to
138+ -- implement the standard type classes present in standard Haskell.
139+ iden,
140+ comp,
141+ fromF,
142+ fromFN,
143+
144+ -- * Matrix printing
145+ pretty,
146+ prettyPrint,
147+
148+ -- * Other
149+ toBool,
150+ fromBool,
151+ compRel,
152+ divR,
153+ divL,
154+ divS,
155+ fromFRelN,
156+ toRelN,
157+ negateM,
158+ orM,
159+ andM,
160+ subM,
161+
162+ -- * Semantics
163+ Construct
164+ )
165+ where
166+
167+import LAoP.Utils.Internal
168+import Data.Bool
169+import Data.Functor.Contravariant
170+import Data.Kind
171+import Data.List
172+import Data.Maybe
173+import Data.Proxy
174+import Data.Void
175+import GHC.TypeLits
176+import Data.Type.Equality
177+import GHC.Generics
178+import Control.DeepSeq
179+import Prelude hiding (id, (.))
180+
181+-- | LAoP (Linear Algebra of Programming) Inductive Matrix definition.
182+data Matrix e cols rows where
183+ Empty :: Matrix e Void Void
184+ One :: e -> Matrix e () ()
185+ Join :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
186+ Fork :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
187+
188+deriving instance (Show e) => Show (Matrix e cols rows)
189+
190+-- | Type family that computes the cardinality of a given type dimension.
191+--
192+-- It can also count the cardinality of custom types that implement the
193+-- 'Generic' instance.
194+type family Count (d :: Type) :: Nat where
195+ Count (Natural n m) = (m - n) + 1
196+ Count (List a) = (^) 2 (Count a)
197+ Count (Either a b) = (+) (Count a) (Count b)
198+ Count (a, b) = (*) (Count a) (Count b)
199+ Count (a -> b) = (^) (Count b) (Count a)
200+ -- Generics
201+ Count (M1 _ _ f p) = Count (f p)
202+ Count (K1 _ _ _) = 1
203+ Count (V1 _) = 0
204+ Count (U1 _) = 1
205+ Count ((:*:) a b p) = Count (a p) * Count (b p)
206+ Count ((:+:) a b p) = Count (a p) + Count (b p)
207+ Count d = Count (Rep d R)
208+
209+-- | Type family that computes of a given type dimension from a given natural
210+--
211+-- Thanks to Li-Yao Xia this type family is super fast.
212+type family FromNat (n :: Nat) :: Type where
213+ FromNat 0 = Void
214+ FromNat 1 = ()
215+ FromNat n = FromNat' (Mod n 2 == 0) (FromNat (Div n 2))
216+
217+type family FromNat' (b :: Bool) (m :: Type) :: Type where
218+ FromNat' 'True m = Either m m
219+ FromNat' 'False m = Either () (Either m m)
220+
221+-- | Type family that normalizes the representation of a given data
222+-- structure
223+type family Normalize (d :: Type) :: Type where
224+ Normalize (Either a b) = Either (Normalize a) (Normalize b)
225+ Normalize d = FromNat (Count d)
226+
227+-- | Constraint type synonyms to keep the type signatures less convoluted
228+type Countable a = KnownNat (Count a)
229+type CountableDimensions a b = (Countable a, Countable b)
230+type Liftable a b = (Eq b, Constructable a b, Enumerable a)
231+type Enumerable a = (Enum a, Bounded a)
232+type ConstructNorm a = (Enum a, Enum (Normalize a))
233+type ConstructableNorm a b = (ConstructNorm a, ConstructNorm b)
234+type ConstructN a = Construct (Normalize a)
235+type Constructable a b = (Construct a, Construct b)
236+type ConstructableN a b = (Construct (Normalize a), Construct (Normalize b))
237+
238+-- | It isn't possible to implement the 'id' function so it's
239+-- implementation is 'undefined'. However 'comp' can be and this partial
240+-- class implementation exists just to make the code more readable.
241+--
242+-- Please use 'iden' instead.
243+instance (Num e) => Category (Matrix e) where
244+ type Object (Matrix e) a = Liftable a a
245+ id = iden
246+ (.) = comp
247+
248+instance NFData e => NFData (Matrix e cols rows) where
249+ rnf Empty = ()
250+ rnf (One e) = rnf e
251+ rnf (Join a b) = rnf a `seq` rnf b
252+ rnf (Fork a b) = rnf a `seq` rnf b
253+
254+instance Eq e => Eq (Matrix e cols rows) where
255+ Empty == Empty = True
256+ (One a) == (One b) = a == b
257+ (Join a b) == (Join c d) = a == c && b == d
258+ (Fork a b) == (Fork c d) = a == c && b == d
259+ x@(Fork _ _) == y@(Join _ _) = x == abideJF y
260+ x@(Join _ _) == y@(Fork _ _) = abideJF x == y
261+
262+instance Num e => Num (Matrix e cols rows) where
263+
264+ a + b = zipWithM (+) a b
265+
266+ a - b = zipWithM (-) a b
267+
268+ a * b = zipWithM (*) a b
269+
270+ abs Empty = Empty
271+ abs (One a) = One (abs a)
272+ abs (Join a b) = Join (abs a) (abs b)
273+ abs (Fork a b) = Fork (abs a) (abs b)
274+
275+ signum Empty = Empty
276+ signum (One a) = One (signum a)
277+ signum (Join a b) = Join (signum a) (signum b)
278+ signum (Fork a b) = Fork (signum a) (signum b)
279+
280+instance Ord e => Ord (Matrix e cols rows) where
281+ Empty <= Empty = True
282+ (One a) <= (One b) = a <= b
283+ (Join a b) <= (Join c d) = (a <= c) && (b <= d)
284+ (Fork a b) <= (Fork c d) = (a <= c) && (b <= d)
285+ x@(Fork _ _) <= y@(Join _ _) = x <= abideJF y
286+ x@(Join _ _) <= y@(Fork _ _) = abideJF x <= y
287+
288+-- Primitives
289+
290+-- | Empty matrix constructor
291+empty :: Matrix e Void Void
292+empty = Empty
293+
294+-- | Unit matrix constructor
295+one :: e -> Matrix e () ()
296+one = One
297+
298+-- | Matrix 'Join' constructor
299+join :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
300+join = Join
301+
302+infixl 3 |||
303+
304+-- | Matrix 'Join' constructor
305+(|||) :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
306+(|||) = Join
307+
308+-- | Matrix 'Fork' constructor
309+fork :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
310+fork = Fork
311+
312+infixl 2 ===
313+
314+-- | Matrix 'Fork' constructor
315+(===) :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
316+(===) = Fork
317+
318+-- Construction
319+
320+-- | Constructs a column vector matrix
321+colL :: (FromLists e () rows) => [e] -> Matrix e () rows
322+colL = fromLists . map (: [])
323+
324+-- | Constructs a row vector matrix
325+rowL :: (FromLists e cols ()) => [e] -> Matrix e cols ()
326+rowL = fromLists . (: [])
327+
328+-- Conversion
329+
330+-- | Converts a matrix to a list of lists of elements.
331+toLists :: Matrix e cols rows -> [[e]]
332+toLists Empty = []
333+toLists (One e) = [[e]]
334+toLists (Fork l r) = toLists l ++ toLists r
335+toLists (Join l r) = zipWith (++) (toLists l) (toLists r)
336+
337+-- | Converts a matrix to a list of elements.
338+toList :: Matrix e cols rows -> [e]
339+toList = concat . toLists
340+
341+-- Zeros Matrix
342+
343+-- | The zero matrix. A matrix wholly filled with zeros.
344+zeros :: (Num e, Constructable cols rows, Enumerable cols) => Matrix e cols rows
345+zeros = matrixBuilder (const 0)
346+
347+-- Ones Matrix
348+
349+-- | The ones matrix. A matrix wholly filled with ones.
350+--
351+-- Also known as T (Top) matrix.
352+ones :: (Num e, Constructable cols rows, Enumerable cols) => Matrix e cols rows
353+ones = matrixBuilder (const 1)
354+
355+-- Const Matrix
356+
357+-- | The constant matrix constructor. A matrix wholly filled with a given
358+-- value.
359+constant :: (Num e, Constructable cols rows, Enumerable cols) => e -> Matrix e cols rows
360+constant e = matrixBuilder (const e)
361+
362+-- Bang Matrix
363+
364+-- | The T (Top) row vector matrix.
365+bang :: (Num e, Constructable cols rows, Enumerable cols) => Matrix e cols ()
366+bang = ones
367+
368+-- | Point constant matrix
369+point :: (Num e, Liftable () a) => a -> Matrix e () a
370+point = fromF . const
371+
372+-- iden Matrix
373+
374+-- | iden matrix.
375+iden :: (Num e, Liftable cols cols) => Matrix e cols cols
376+iden = fromF id
377+
378+-- Matrix composition (MMM)
379+
380+-- | Matrix composition. Equivalent to matrix-matrix multiplication.
381+--
382+-- This definition takes advantage of divide-and-conquer and fusion laws
383+-- from LAoP.
384+comp :: (Num e) => Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
385+comp Empty Empty = Empty
386+comp (One a) (One b) = One (a * b)
387+comp (Join a b) (Fork c d) = comp a c + comp b d -- Divide-and-conquer law
388+comp (Fork a b) c = Fork (comp a c) (comp b c) -- Fork fusion law
389+comp c (Join a b) = Join (comp c a) (comp c b) -- Join fusion law
390+{-# NOINLINE comp #-}
391+{-# RULES
392+ "comp/iden1" forall m. comp m iden = m ;
393+ "comp/iden2" forall m. comp iden m = m
394+#-}
395+
396+-- Scalar multiplication of matrices
397+
398+infixl 7 .|
399+-- | Scalar multiplication of matrices.
400+(.|) :: Num e => e -> Matrix e cols rows -> Matrix e cols rows
401+(.|) _ Empty = Empty
402+(.|) e (One a) = One (e * a)
403+(.|) e (Join a b) = Join (e .| a) (e .| b)
404+(.|) e (Fork a b) = Fork (e .| a) (e .| b)
405+
406+-- Scalar division of matrices
407+
408+infixl 7 ./
409+-- | Scalar multiplication of matrices.
410+(./) :: Fractional e => Matrix e cols rows -> e -> Matrix e cols rows
411+(./) Empty _ = Empty
412+(./) (One a) e = One (a / e)
413+(./) (Join a b) e = Join (a ./ e) (b ./ e)
414+(./) (Fork a b) e = Fork (a ./ e) (b ./ e)
415+
416+-- Projections
417+
418+-- | Biproduct first component projection
419+p1 :: (Num e, Eq m, Constructable m n, Enumerable m, Enumerable n) => Matrix e (Either m n) m
420+p1 = join iden zeros
421+
422+-- | Biproduct second component projection
423+p2 :: (Num e, Eq n, Constructable m n, Enumerable m, Enumerable n) => Matrix e (Either m n) n
424+p2 = join zeros iden
425+
426+-- Injections
427+
428+-- | Biproduct first component injection
429+i1 :: (Num e, Eq m, Constructable m n, Enumerable m, Enumerable n) => Matrix e m (Either m n)
430+i1 = tr p1
431+
432+-- | Biproduct second component injection
433+i2 :: (Num e, Eq n, Constructable m n, Enumerable m, Enumerable n) => Matrix e n (Either m n)
434+i2 = tr p2
435+
436+-- Dimensions
437+
438+-- | Obtain the number of rows.
439+--
440+-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
441+-- dimensions in constant time.
442+--
443+-- TODO: A 'rows' function that does not need the 'KnownNat' constraint in
444+-- exchange for performance.
445+rows :: forall e cols rows. (Countable rows) => Matrix e cols rows -> Int
446+rows _ = fromInteger $ natVal (Proxy :: Proxy (Count rows))
447+
448+-- | Obtain the number of columns.
449+--
450+-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
451+-- dimensions in constant time.
452+--
453+-- TODO: A 'columns' function that does not need the 'KnownNat' constraint in
454+-- exchange for performance.
455+columns :: forall e cols rows. (Countable cols) => Matrix e cols rows -> Int
456+columns _ = fromInteger $ natVal (Proxy :: Proxy (Count cols))
457+
458+-- Coproduct Bifunctor
459+
460+infixl 5 -|-
461+
462+-- | Matrix coproduct functor also known as matrix direct sum.
463+(-|-) ::
464+ ( Num e,
465+ Eq k,
466+ Eq j,
467+ Constructable k j,
468+ Enumerable k,
469+ Enumerable j
470+ ) => Matrix e n k -> Matrix e m j -> Matrix e (Either n m) (Either k j)
471+(-|-) a b = Join (i1 . a) (i2 . b)
472+
473+-- Khatri Rao Product and projections
474+
475+-- | Khatri Rao product first component projection matrix.
476+fstM ::
477+ forall e a b .
478+ ( Num e,
479+ Eq a,
480+ ConstructableN (a, b) a,
481+ ConstructableNorm (a, b) a,
482+ Enumerable a,
483+ Enumerable b
484+ ) => Matrix e (Normalize (a, b)) (Normalize a)
485+fstM = fromFN (fst :: (a, b) -> a)
486+
487+-- | Khatri Rao product second component projection matrix.
488+sndM ::
489+ forall e a b .
490+ ( Num e,
491+ Eq b,
492+ ConstructableN (a, b) b,
493+ ConstructableNorm (a, b) b,
494+ Enumerable a,
495+ Enumerable b
496+ ) => Matrix e (Normalize (a, b)) (Normalize b)
497+sndM = fromFN (snd :: (a, b) -> b)
498+
499+-- | Khatri Rao Matrix product also known as matrix pairing.
500+--
501+-- NOTE: That this is not a true categorical product, see for instance:
502+--
503+-- @
504+-- | fstM . kr a b == a
505+-- kr a b ==> |
506+-- | sndM . kr a b == b
507+-- @
508+--
509+-- __Emphasis__ on the implication symbol.
510+kr ::
511+ forall e cols a b .
512+ ( Num e,
513+ Eq a,
514+ Eq b,
515+ ConstructableN a (a, b),
516+ ConstructN b,
517+ ConstructableNorm a b,
518+ ConstructNorm (a, b),
519+ Enumerable a,
520+ Enumerable b
521+ ) => Matrix e cols (Normalize a) -> Matrix e cols (Normalize b) -> Matrix e cols (Normalize (a, b))
522+kr a b =
523+ let fstM' = fstM @e @a @b
524+ sndM' = sndM @e @a @b
525+ in (tr fstM' . a) * (tr sndM' . b)
526+
527+-- Product Bifunctor (Kronecker)
528+
529+infixl 4 ><
530+
531+type Kronecker e m n p q =
532+ ( Num e,
533+ Eq m,
534+ Eq n,
535+ Eq p,
536+ Eq q,
537+ ConstructableN m n,
538+ ConstructableNorm m (m, n),
539+ ConstructNorm n,
540+ ConstructN (m, n),
541+ ConstructableN p q,
542+ ConstructableNorm p (p, q),
543+ ConstructNorm q,
544+ ConstructN (p, q),
545+ Enumerable m,
546+ Enumerable n,
547+ Enumerable p,
548+ Enumerable q
549+ )
550+
551+-- | Matrix product functor also known as kronecker product
552+(><) ::
553+ forall e m p n q .
554+ Kronecker e m n p q
555+ => Matrix e (Normalize m) (Normalize p)
556+ -> Matrix e (Normalize n) (Normalize q)
557+ -> Matrix e (Normalize (m, n)) (Normalize (p, q))
558+(><) a b =
559+ let fstM' = fstM @e @m @n
560+ sndM' = sndM @e @m @n
561+ in kr @e @(Normalize (m, n)) @p @q (a . fstM') (b . sndM')
562+
563+-- Matrix abide Join Fork
564+
565+-- | Matrix "abiding" following the 'Join'-'Fork' exchange law.
566+--
567+-- Law:
568+--
569+-- @
570+-- 'Join' ('Fork' a c) ('Fork' b d) == 'Fork' ('Join' a b) ('Join' c d)
571+-- @
572+abideJF :: Matrix e cols rows -> Matrix e cols rows
573+abideJF (Join (Fork a c) (Fork b d)) = Fork (Join (abideJF a) (abideJF b)) (Join (abideJF c) (abideJF d)) -- Join-Fork abide law
574+abideJF Empty = Empty
575+abideJF (One e) = One e
576+abideJF (Join a b) = Join (abideJF a) (abideJF b)
577+abideJF (Fork a b) = Fork (abideJF a) (abideJF b)
578+
579+-- Matrix abide Fork Join
580+
581+-- | Matrix "abiding" followin the 'Fork'-'Join' abide law.
582+--
583+-- @
584+-- 'Fork' ('Join' a b) ('Join' c d) == 'Join' ('Fork' a c) ('Fork' b d)
585+-- @
586+abideFJ :: Matrix e cols rows -> Matrix e cols rows
587+abideFJ (Fork (Join a b) (Join c d)) = Join (Fork (abideFJ a) (abideFJ c)) (Fork (abideFJ b) (abideFJ d)) -- Fork-Join abide law
588+abideFJ Empty = Empty
589+abideFJ (One e) = One e
590+abideFJ (Join a b) = Join (abideFJ a) (abideFJ b)
591+abideFJ (Fork a b) = Fork (abideFJ a) (abideFJ b)
592+
593+-- Matrix transposition
594+
595+-- | Matrix transposition.
596+tr :: Matrix e cols rows -> Matrix e rows cols
597+tr Empty = Empty
598+tr (One e) = One e
599+tr (Join a b) = Fork (tr a) (tr b)
600+tr (Fork a b) = Join (tr a) (tr b)
601+
602+-- Selective 'select' operator
603+
604+-- | Selective functors 'select' operator equivalent inspired by the
605+-- ArrowMonad solution presented in the paper.
606+select :: (Num e, Liftable b b) => Matrix e cols (Either a b) -> Matrix e a b -> Matrix e cols b
607+select (Fork a b) y = y . a + b -- Divide-and-conquer law
608+select (Join (Fork a c) (Fork b d)) y = join (y . a + c) (y . b + d) -- Pattern matching + DnC law
609+select m y = join y id . m
610+
611+branch ::
612+ ( Num e,
613+ Eq a,
614+ Eq b,
615+ Eq c,
616+ Constructable a b,
617+ Construct c,
618+ Enumerable a,
619+ Enumerable b,
620+ Enumerable c
621+ )
622+ => Matrix e cols (Either a b) -> Matrix e a c -> Matrix e b c -> Matrix e cols c
623+branch x l r = f x `select` g l `select` r
624+ where
625+ f m = fork (tr i1) (i1 . tr i2) . m
626+ g m = i2 . m
627+
628+-- Pretty print
629+
630+prettyAux :: Show e => [[e]] -> [[e]] -> String
631+prettyAux [] _ = ""
632+prettyAux [[e]] m = "│ " ++ fill (show e) ++ " │\n"
633+ where
634+ v = fmap show m
635+ widest = maximum $ fmap length v
636+ fill str = replicate (widest - length str - 2) ' ' ++ str
637+prettyAux [h] m = "│ " ++ fill (unwords $ map show h) ++ " │\n"
638+ where
639+ v = fmap show m
640+ widest = maximum $ fmap length v
641+ fill str = replicate (widest - length str - 2) ' ' ++ str
642+prettyAux (h : t) l = "│ " ++ fill (unwords $ map show h) ++ " │\n" ++
643+ prettyAux t l
644+ where
645+ v = fmap show l
646+ widest = maximum $ fmap length v
647+ fill str = replicate (widest - length str - 2) ' ' ++ str
648+
649+-- | Matrix pretty printer
650+pretty :: (CountableDimensions cols rows, Show e) => Matrix e cols rows -> String
651+pretty m = concat
652+ [ "┌ ", unwords (replicate (columns m) blank), " ┐\n"
653+ , unlines
654+ [ "│ " ++ unwords (fmap (\j -> fill $ show $ getElem i j m) [1..columns m]) ++ " │" | i <- [1..rows m] ]
655+ , "└ ", unwords (replicate (columns m) blank), " ┘"
656+ ]
657+ where
658+ strings = map show (toList m)
659+ widest = maximum $ map length strings
660+ fill str = replicate (widest - length str) ' ' ++ str
661+ blank = fill ""
662+ safeGet i j m
663+ | i > rows m || j > columns m || i < 1 || j < 1 = Nothing
664+ | otherwise = Just $ unsafeGet i j m (toList m)
665+ unsafeGet i j m l = l !! encode (columns m) (i,j)
666+ encode m (i,j) = (i-1)*m + j - 1
667+ getElem i j m =
668+ fromMaybe
669+ (error $
670+ "getElem: Trying to get the "
671+ ++ show (i, j)
672+ ++ " element from a "
673+ ++ show (rows m) ++ "x" ++ show (columns m)
674+ ++ " matrix."
675+ )
676+ (safeGet i j m)
677+
678+-- | Matrix pretty printer
679+prettyPrint :: (CountableDimensions cols rows, Show e) => Matrix e cols rows -> IO ()
680+prettyPrint = putStrLn . pretty
681+
682+-- | Zip two matrices with a given binary function
683+zipWithM :: (e -> f -> g) -> Matrix e cols rows -> Matrix f cols rows -> Matrix g cols rows
684+zipWithM _ Empty Empty = Empty
685+zipWithM f (One a) (One b) = One (f a b)
686+zipWithM f (Join a b) (Join c d) = Join (zipWithM f a c) (zipWithM f b d)
687+zipWithM f (Fork a b) (Fork c d) = Fork (zipWithM f a c) (zipWithM f b d)
688+zipWithM f x@(Fork _ _) y@(Join _ _) = zipWithM f x (abideJF y)
689+zipWithM f x@(Join _ _) y@(Fork _ _) = zipWithM f (abideJF x) y
690+
691+-- Relational operators functions
692+
693+type Boolean = Natural 0 1
694+type Relation a b = Matrix Boolean a b
695+
696+-- | Helper conversion function
697+toBool :: (Num e, Eq e) => e -> Bool
698+toBool n
699+ | n == 0 = False
700+ | n == 1 = True
701+
702+-- | Helper conversion function
703+fromBool :: Bool -> Natural 0 1
704+fromBool True = nat 1
705+fromBool False = nat 0
706+
707+-- | Relational negation
708+negateM :: Relation cols rows -> Relation cols rows
709+negateM Empty = Empty
710+negateM (One (Nat p)) = One (Nat (negate p))
711+negateM (Join a b) = Join (negateM a) (negateM b)
712+negateM (Fork a b) = Fork (negateM a) (negateM b)
713+
714+-- | Relational addition
715+orM :: Relation cols rows -> Relation cols rows -> Relation cols rows
716+orM Empty Empty = Empty
717+orM (One a) (One b) = One (fromBool (toBool a || toBool b))
718+orM (Join a b) (Join c d) = Join (orM a c) (orM b d)
719+orM (Fork a b) (Fork c d) = Fork (orM a c) (orM b d)
720+orM x@(Fork _ _) y@(Join _ _) = orM x (abideJF y)
721+orM x@(Join _ _) y@(Fork _ _) = orM (abideJF x) y
722+
723+-- | Relational multiplication
724+andM :: Relation cols rows -> Relation cols rows -> Relation cols rows
725+andM Empty Empty = Empty
726+andM (One a) (One b) = One (fromBool (toBool a && toBool b))
727+andM (Join a b) (Join c d) = Join (andM a c) (andM b d)
728+andM (Fork a b) (Fork c d) = Fork (andM a c) (andM b d)
729+andM x@(Fork _ _) y@(Join _ _) = andM x (abideJF y)
730+andM x@(Join _ _) y@(Fork _ _) = andM (abideJF x) y
731+
732+-- | Relational subtraction
733+subM :: Relation cols rows -> Relation cols rows -> Relation cols rows
734+subM Empty Empty = Empty
735+subM (One a) (One b) = if a - b < nat 0 then One (nat 0) else One (a - b)
736+subM (Join a b) (Join c d) = Join (subM a c) (subM b d)
737+subM (Fork a b) (Fork c d) = Fork (subM a c) (subM b d)
738+subM x@(Fork _ _) y@(Join _ _) = subM x (abideJF y)
739+subM x@(Join _ _) y@(Fork _ _) = subM (abideJF x) y
740+
741+-- | Matrix relational composition.
742+compRel :: Relation cr rows -> Relation cols cr -> Relation cols rows
743+compRel Empty Empty = Empty
744+compRel (One a) (One b) = One (fromBool (toBool a && toBool b))
745+compRel (Join a b) (Fork c d) = orM (compRel a c) (compRel b d) -- Divide-and-conquer law
746+compRel (Fork a b) c = Fork (compRel a c) (compRel b c) -- Fork fusion law
747+compRel c (Join a b) = Join (compRel c a) (compRel c b) -- Join fusion law
748+
749+-- | Matrix relational right division
750+divR :: Relation b c -> Relation b a -> Relation a c
751+divR Empty Empty = Empty
752+divR (One a) (One b) = One (fromBool (not (toBool b) || toBool a)) -- b implies a
753+divR (Join a b) (Join c d) = andM (divR a c) (divR b d)
754+divR (Fork a b) c = Fork (divR a c) (divR b c)
755+divR c (Fork a b) = Join (divR c a) (divR c b)
756+
757+-- | Matrix relational left division
758+divL :: Relation c b -> Relation a b -> Relation a c
759+divL x y = tr (divR (tr y) (tr x))
760+
761+-- | Matrix relational symmetric division
762+divS :: Relation c a -> Relation b a -> Relation c b
763+divS s r = divL r s `intersection` divR (tr r) (tr s)
764+ where
765+ intersection = andM
766+
767+-- | Lifts functions to relations with dimensions matching @a@ and @b@
768+-- cardinality's.
769+fromFRelN ::
770+ ( Eq b,
771+ ConstructableNorm a b,
772+ ConstructableN a b,
773+ Enumerable a
774+ )
775+ => (a -> b) -> Relation (Normalize a) (Normalize b)
776+fromFRelN = fromFN
777+
778+-- | Lifts a relation function to a Boolean Matrix
779+toRelN ::
780+ ( ConstructableN a b,
781+ ConstructableNorm a b,
782+ Enumerable a
783+ )
784+ => (a -> b -> Bool) -> Relation (Normalize a) (Normalize b)
785+toRelN f = matrixBuilderN (\a -> if uncurry f a then 1 else 0)
786+
787+----------------------------- Linear map semantics -----------------------------
788+newtype Vector e a = Vector { at :: a -> e }
789+
790+instance Contravariant (Vector e) where
791+ contramap f (Vector g) = Vector (g . f)
792+
793+instance Num e => Num (Vector e a) where
794+ fromInteger = Vector . const . fromInteger
795+
796+ (+) = liftV2 (+)
797+ (-) = liftV2 (-)
798+ (*) = liftV2 (*)
799+ abs = liftV1 abs
800+ negate = liftV1 negate
801+ signum = error "No sensible definition"
802+
803+liftV1 :: (e -> e) -> Vector e a -> Vector e a
804+liftV1 f x = Vector (f . at x)
805+
806+liftV2 :: (e -> e -> e) -> Vector e a -> Vector e a -> Vector e a
807+liftV2 f x y = Vector (\a -> f (at x a) (at y a))
808+
809+-- Semantics of Matrix e a b
810+type LinearMap e a b = Vector e a -> Vector e b
811+
812+semantics :: Num e => Matrix e a b -> LinearMap e a b
813+semantics m = case m of
814+ Empty -> id
815+ One e -> const (Vector (const e))
816+ Join x y -> \v -> semantics x (Left >$< v) + semantics y (Right >$< v)
817+ Fork x y -> \v -> Vector $ either (at (semantics x v)) (at (semantics y v))
818+
819+padLeft :: Num e => Vector e b -> Vector e (Either a b)
820+padLeft v = Vector $ \case Left _ -> 0
821+ Right b -> at v b
822+
823+padRight :: Num e => Vector e a -> Vector e (Either a b)
824+padRight v = Vector $ \case Left a -> at v a
825+ Right _ -> 0
826+
827+dot :: (Num e, Enumerable a) => Vector e a -> Vector e a -> e
828+dot x y = sum [ at x a * at y a | a <- enumerate ]
829+
830+--------------------------------- Construction ---------------------------------
831+
832+class Construct a where
833+ row :: Num e => Vector e a -> Matrix e a ()
834+
835+ linearMap :: (Construct b, Num e) => LinearMap e a b -> Matrix e a b
836+
837+instance Construct () where
838+ row v = one (at v ())
839+
840+ linearMap m = col (m 1)
841+
842+instance (Constructable a b) => Construct (Either a b) where
843+ row v = row (Left >$< v) ||| row (Right >$< v)
844+
845+ linearMap m = linearMap (m . padRight) ||| linearMap (m . padLeft)
846+
847+col :: (Construct a, Num e) => Vector e a -> Matrix e () a
848+col = tr . row
849+
850+-- | Matrix builder function. Constructs a matrix provided with
851+-- a construction function that operates with canonical types.
852+matrixBuilder :: (Num e, Constructable a b, Enumerable a) => ((a, b) -> e) -> Matrix e a b
853+matrixBuilder f = linearMap $ \v -> Vector $ \b -> dot v $ Vector $ \a -> f (a, b)
854+
855+-- | Lifts functions to matrices.
856+fromF :: (Num e, Liftable a b) => (a -> b) -> Matrix e a b
857+fromF f = matrixBuilder (\(a, b) -> if f a == b then 1 else 0)
858+
859+-------------------------------- Deconstruction --------------------------------
860+enumerate :: Enumerable a => [a]
861+enumerate = [minBound .. maxBound]
862+
863+basis :: (Enumerable a, Eq a, Num e) => [Vector e a]
864+basis = [ Vector (bool 0 1 . (==a)) | a <- enumerate ]
865+
866+toLists' :: (Enumerable a, Enumerable b, Eq a, Num e) => Matrix e a b -> [[e]]
867+toLists' m = transpose
868+ [ [ at r i | i <- enumerate ] | c <- basis, let r = semantics m c ]
869+
870+dump :: (Enumerable a, Enumerable b, Eq a, Num e, Show e) => Matrix e a b -> IO ()
871+dump = mapM_ print . toLists'
872+
873+------------------------------- Normalised types -------------------------------
874+class Profunctor p where
875+ dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
876+
877+instance Profunctor (->) where
878+ dimap f g h = g . h . f
879+
880+toNorm :: ConstructNorm a => a -> Normalize a
881+toNorm = toEnum . fromEnum
882+
883+fromNorm :: ConstructNorm a => Normalize a -> a
884+fromNorm = toEnum . fromEnum
885+
886+rowN :: (ConstructN a, ConstructNorm a, Num e) => Vector e a -> Matrix e (Normalize a) ()
887+rowN = row . contramap fromNorm
888+
889+linearMapN :: (ConstructableN a b, ConstructableNorm a b, Num e)
890+ => LinearMap e a b -> Matrix e (Normalize a) (Normalize b)
891+linearMapN = linearMap . dimap (contramap toNorm) (contramap fromNorm)
892+
893+colN :: (ConstructN a, ConstructNorm a, Num e) => Vector e a -> Matrix e () (Normalize a)
894+colN = tr . rowN
895+
896+-- | Matrix builder function. Constructs a matrix provided with
897+-- a construction function that operates with arbitrary types.
898+matrixBuilderN :: (Num e, ConstructableN a b, ConstructableNorm a b, Enumerable a)
899+ => ((a, b) -> e) -> Matrix e (Normalize a) (Normalize b)
900+matrixBuilderN f = linearMapN $ \v -> Vector $ \b -> dot v $ Vector $ \a -> f (a, b)
901+
902+-- | Lifts functions to matrices with dimensions matching @a@ and @b@
903+-- cardinality's.
904+fromFN :: (Num e, Eq b, ConstructableN a b, ConstructableNorm a b, Enumerable a)
905+ => (a -> b) -> Matrix e (Normalize a) (Normalize b)
906+fromFN f = matrixBuilderN (\(a, b) -> if f a == b then 1 else 0)
907+
908+------------------------------- Unsafe fromLists matrix construction -------------------------------
909+
910+-- | Type class for defining the 'fromList' conversion function.
911+--
912+-- Given that it is not possible to branch on types at the term level type
913+-- classes are needed very much like an inductive definition but on types.
914+class FromLists e cols rows where
915+ -- | Build a matrix out of a list of list of elements. Throws a runtime
916+ -- error if the dimensions do not match.
917+ fromLists :: [[e]] -> Matrix e cols rows
918+
919+instance FromLists e Void Void where
920+ fromLists [] = Empty
921+ fromLists _ = error "Wrong dimensions"
922+
923+instance {-# OVERLAPPING #-} FromLists e () () where
924+ fromLists [[e]] = One e
925+ fromLists _ = error "Wrong dimensions"
926+
927+instance {-# OVERLAPPING #-} (FromLists e cols ()) => FromLists e (Either () cols) () where
928+ fromLists [h : t] = Join (One h) (fromLists [t])
929+ fromLists _ = error "Wrong dimensions"
930+
931+instance {-# OVERLAPPABLE #-} (FromLists e a (), FromLists e b (), Countable a) => FromLists e (Either a b) () where
932+ fromLists [l] =
933+ let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
934+ in Join (fromLists [take rowsA l]) (fromLists [drop rowsA l])
935+ fromLists _ = error "Wrong dimensions"
936+
937+instance {-# OVERLAPPING #-} (FromLists e () rows) => FromLists e () (Either () rows) where
938+ fromLists ([h] : t) = Fork (One h) (fromLists t)
939+ fromLists _ = error "Wrong dimensions"
940+
941+instance {-# OVERLAPPABLE #-} (FromLists e () a, FromLists e () b, Countable a) => FromLists e () (Either a b) where
942+ fromLists l@([_] : _) =
943+ let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
944+ in Fork (fromLists (take rowsA l)) (fromLists (drop rowsA l))
945+ fromLists _ = error "Wrong dimensions"
946+
947+instance {-# OVERLAPPABLE #-} (FromLists e (Either a b) c, FromLists e (Either a b) d, Countable c) => FromLists e (Either a b) (Either c d) where
948+ fromLists l@(h : t) =
949+ let lh = length h
950+ rowsC = fromInteger (natVal (Proxy :: Proxy (Count c)))
951+ condition = all ((== lh) . length) t
952+ in if lh > 0 && condition
953+ then Fork (fromLists (take rowsC l)) (fromLists (drop rowsC l))
954+ else error "Not all rows have the same length"
src/LAoP/Matrix/Type.hs+190−196
@@ -87,10 +87,9 @@ module LAoP.Matrix.Type
87 fromLists,
87 fromLists,
88 toLists,
88 toLists,
89 toList,
89 toList,
90− matrixBuilder',
91 matrixBuilder,
90 matrixBuilder,
92− row,
91+ rowL,
93− col,
92+ colL,
94 zeros,
93 zeros,
95 ones,
94 ones,
96 bang,
95 bang,
@@ -125,7 +124,7 @@ module LAoP.Matrix.Type
125 (./),
124 (./),
126
125
127 -- ** McCarthy's Conditional
126 -- ** McCarthy's Conditional
128− cond,
127+ -- cond,
129
128
130 -- ** Matrix "abiding"
129 -- ** Matrix "abiding"
131 abideJF,
130 abideJF,
@@ -168,7 +167,6 @@ module LAoP.Matrix.Type
168 -- implement the standard type classes present in standard Haskell.
167 -- implement the standard type classes present in standard Haskell.
169 iden,
168 iden,
170 comp,
169 comp,
171− fromF',
172 fromF,
170 fromF,
173
171
174 -- * Relation
172 -- * Relation
@@ -181,12 +179,11 @@ module LAoP.Matrix.Type
181where
179where
182
180
183import Data.Void
181import Data.Void
184−import Data.Proxy
185import Data.Kind
182import Data.Kind
186import GHC.TypeLits
183import GHC.TypeLits
187import Control.DeepSeq
184import Control.DeepSeq
188import LAoP.Utils
185import LAoP.Utils
189−import qualified LAoP.Matrix.Internal as I
186+import qualified LAoP.Matrix.Alternative as I
190import Prelude hiding (id, (.))
187import Prelude hiding (id, (.))
191
188
192newtype Matrix e (cols :: Type) (rows :: Type) = M (I.Matrix e (I.Normalize cols) (I.Normalize rows))
189newtype Matrix e (cols :: Type) (rows :: Type) = M (I.Matrix e (I.Normalize cols) (I.Normalize rows))
@@ -198,27 +195,30 @@ type CountableDimensions a b = (Countable a, Countable b)
198type CountableN a = KnownNat (I.Count (I.Normalize a))
195type CountableN a = KnownNat (I.Count (I.Normalize a))
199type CountableDimensionsN a b = (CountableN a, CountableN b)
196type CountableDimensionsN a b = (CountableN a, CountableN b)
200type FromListsN e a b = I.FromLists e (I.Normalize a) (I.Normalize b)
197type FromListsN e a b = I.FromLists e (I.Normalize a) (I.Normalize b)
201−type Liftable e a b = (Bounded a, Bounded b, Enum a, Enum b, Eq b, Num e, Ord e)
198+type Liftable a b = (Eq b, Enumerable a, Enum a, EnumN a, Enum b, EnumN b, ConstructableN a b)
202type Trivial a = I.Normalize (I.Normalize a) ~ I.Normalize (I.Normalize (I.Normalize a))
199type Trivial a = I.Normalize (I.Normalize a) ~ I.Normalize (I.Normalize (I.Normalize a))
203type Trivial2 a = I.Normalize a ~ I.Normalize (I.Normalize a)
200type Trivial2 a = I.Normalize a ~ I.Normalize (I.Normalize a)
204−type Trivial3 a = I.FromNat (I.Count (I.Normalize (I.Normalize a))) ~ I.Normalize (I.Normalize a)
205type TrivialP a b = I.Normalize (a, b) ~ I.Normalize (I.Normalize a, I.Normalize b)
201type TrivialP a b = I.Normalize (a, b) ~ I.Normalize (I.Normalize a, I.Normalize b)
202+type EqN a = Eq (I.Normalize a)
203+type EnumN a = Enum (I.Normalize a)
204+type Enumerable a = (Enum a, Bounded a)
205+type EnumerableN a = (Enum (I.Normalize a), Bounded (I.Normalize a))
206+type ConstructNorm a = (Enum a, Enum (I.Normalize a))
207+type ConstructN a = I.Construct (I.Normalize a)
208+type ConstructableN a b = (I.Construct (I.Normalize a), I.Construct (I.Normalize b))
206
209
207-- | It is possible to implement a constrained version of the category type
210-- | It is possible to implement a constrained version of the category type
208-- class.
211-- class.
209instance (Num e) => Category (Matrix e) where
212instance (Num e) => Category (Matrix e) where
210− type Object (Matrix e) a = (FromListsN e a a, CountableN a)
213+ type Object (Matrix e) a = (Num e, EqN a, ConstructN a, EnumerableN a)
211 id = iden
214 id = iden
212 (.) = comp
215 (.) = comp
213
216
214-- | Bifunctor equivalent function
217-- | Bifunctor equivalent function
215bimapM ::
218bimapM ::
216− ( Liftable e a b,
219+ ( Num e,
217− Liftable e c d,
220+ Liftable a b,
218− CountableDimensionsN a c,
221+ Liftable c d
219− CountableDimensionsN b d,
220− FromListsN e d c,
221− FromListsN e b a
222 ) => (a -> b) -> (c -> d) -> Matrix e a c -> Matrix e b d
222 ) => (a -> b) -> (c -> d) -> Matrix e a c -> Matrix e b d
223bimapM f g m = fromF g . m . tr (fromF f)
223bimapM f g m = fromF g . m . tr (fromF f)
224
224
@@ -272,9 +272,8 @@ infixl 2 ===
272
272
273-- | Functor instance equivalent function
273-- | Functor instance equivalent function
274fmapM ::
274fmapM ::
275+ ( Num e,
275− ( Liftable e a b,
276+ Liftable a b
276− CountableDimensionsN a b,
277− FromListsN e b a
278 )
277 )
279 =>
278 =>
280 (a -> b) -> Matrix e c a -> Matrix e c b
279 (a -> b) -> Matrix e c a -> Matrix e c b
@@ -286,29 +285,18 @@ unitM = one 1
286
285
287-- | Applicative instance equivalent 'unit' function,
286-- | Applicative instance equivalent 'unit' function,
288multM ::
287multM ::
289− ( CountableDimensionsN a b,
290− CountableN (a, b),
291− Num e,
288+ ( Num e,
292− FromListsN e (a, b) a,
289+ FstM a b,
293− FromListsN e (a, b) b,
290+ SndM a b
294− TrivialP a b
295 ) => Matrix e c a -> Matrix e c b -> Matrix e c (a, b)
291 ) => Matrix e c a -> Matrix e c b -> Matrix e c (a, b)
296multM = kr
292multM = kr
297
293
298-- | Monad instance equivalent 'return' function,
294-- | Monad instance equivalent 'return' function,
299−returnM ::
295+returnM ::
300− forall e a .
301 ( Num e,
296 ( Num e,
302− Enum e,
297+ Liftable () a
303− Enum a,
304− FromListsN e () a,
305− Countable a
306 ) => a -> Matrix e One a
298 ) => a -> Matrix e One a
307−returnM a = col l
299+returnM = point
308− where
309− i = fromInteger $ natVal (Proxy :: Proxy (I.Count a))
310− x = fromEnum a
311− l = take x [0,0..] ++ [1] ++ take (i - x - 1) [0,0..]
312
300
313-- | Monad instance equivalent '(>>=)' function,
301-- | Monad instance equivalent '(>>=)' function,
314bindM :: (Num e) => Matrix e a b -> Matrix e b c -> Matrix e a c
302bindM :: (Num e) => Matrix e a b -> Matrix e b c -> Matrix e a c
@@ -321,63 +309,39 @@ bindM = flip comp
321fromLists :: (FromListsN e cols rows) => [[e]] -> Matrix e cols rows
309fromLists :: (FromListsN e cols rows) => [[e]] -> Matrix e cols rows
322fromLists = M . I.fromLists
310fromLists = M . I.fromLists
323
311
324−-- | Matrix builder function. Constructs a matrix provided with
325−-- a construction function that operates with indices.
326−matrixBuilder' ::
327− (FromListsN e cols rows, CountableDimensionsN cols rows )
328− => ((Int, Int) -> e) -> Matrix e cols rows
329−matrixBuilder' = M . I.matrixBuilder'
330−
331-- | Matrix builder function. Constructs a matrix provided with
312-- | Matrix builder function. Constructs a matrix provided with
332-- a construction function that operates with arbitrary types.
313-- a construction function that operates with arbitrary types.
333matrixBuilder ::
314matrixBuilder ::
334− ( FromListsN e a b,
315+ ( Num e,
335− Enum a,
316+ Enumerable a,
336− Enum b,
317+ Enum b,
337− Bounded a,
318+ EnumN a,
338− Bounded b,
319+ EnumN b,
339− Eq a,
320+ ConstructableN a b
340− CountableDimensionsN a b
321+ )
341− ) => ((a, b) -> e) -> Matrix e a b
322+ => ((a, b) -> e) -> Matrix e a b
342−matrixBuilder f = M (I.matrixBuilder f)
323+matrixBuilder = M . I.matrixBuilderN
343
324
344-- | Constructs a column vector matrix
325-- | Constructs a column vector matrix
345−col :: (FromListsN e () rows) => [e] -> Matrix e One rows
326+colL :: (FromListsN e () rows) => [e] -> Matrix e One rows
346−col = M . I.col
327+colL = M . I.colL
347
328
348-- | Constructs a row vector matrix
329-- | Constructs a row vector matrix
349−row :: (FromListsN e cols ()) => [e] -> Matrix e cols One
330+rowL :: (FromListsN e cols ()) => [e] -> Matrix e cols One
350−row = M . I.row
331+rowL = M . I.rowL
351−
352−-- | Lifts functions to matrices with arbitrary dimensions.
353−--
354−-- NOTE: Be careful to not ask for a matrix bigger than the cardinality of
355−-- types @a@ or @b@ allows.
356−fromF' ::
357− ( Liftable e a b,
358− CountableDimensionsN cols rows,
359− FromListsN e rows cols
360− ) =>
361− (a -> b) -> Matrix e cols rows
362−fromF' = M . I.fromF'
363
332
364-- | Lifts functions to matrices with dimensions matching @a@ and @b@
333-- | Lifts functions to matrices with dimensions matching @a@ and @b@
365-- cardinality's.
334-- cardinality's.
366fromF ::
335fromF ::
336+ ( Num e,
367− ( Liftable e a b,
337+ Liftable a b
368− CountableDimensionsN a b,
338+ )
369− FromListsN e b a
370− ) =>
371− (a -> b) -> Matrix e a b
339+ => (a -> b) -> Matrix e a b
372−fromF = M . I.fromF
340+fromF = M . I.fromFN
373
341
374-- | Lifts relation functions to Boolean Matrix
342-- | Lifts relation functions to Boolean Matrix
375−toRel ::
376− ( Liftable (Natural 0 1) a b,
377− CountableDimensionsN a b,
378− FromListsN (Natural 0 1) b a
379− ) => (a -> b -> Bool) -> Matrix (Natural 0 1) a b
343+toRel :: Liftable a b => (a -> b -> Bool) -> Matrix (Natural 0 1) a b
380−toRel = M . I.toRel
344+toRel = M . I.toRelN
381
345
382-- Conversion
346-- Conversion
383
347
@@ -393,8 +357,11 @@ toList (M m) = I.toList m
393
357
394-- | The zero matrix. A matrix wholly filled with zeros.
358-- | The zero matrix. A matrix wholly filled with zeros.
395zeros ::
359zeros ::
396− (Num e, FromListsN e cols rows, CountableDimensionsN cols rows)
360+ ( Num e,
361+ ConstructableN cols rows,
362+ EnumerableN cols
363+ )
397− => Matrix e cols rows
364+ => Matrix e cols rows
398zeros = M I.zeros
365zeros = M I.zeros
399
366
400-- Ones Matrix
367-- Ones Matrix
@@ -403,8 +370,11 @@ zeros = M I.zeros
403--
370--
404-- Also known as T (Top) matrix.
371-- Also known as T (Top) matrix.
405ones ::
372ones ::
406− (Num e, FromListsN e cols rows, CountableDimensionsN cols rows)
373+ ( Num e,
374+ ConstructableN cols rows,
375+ EnumerableN cols
376+ )
407− => Matrix e cols rows
377+ => Matrix e cols rows
408ones = M I.ones
378ones = M I.ones
409
379
410-- Const Matrix
380-- Const Matrix
@@ -412,28 +382,28 @@ ones = M I.ones
412-- | The constant matrix constructor. A matrix wholly filled with a given
382-- | The constant matrix constructor. A matrix wholly filled with a given
413-- value.
383-- value.
414constant ::
384constant ::
415− (Num e, FromListsN e cols rows, CountableDimensionsN cols rows)
385+ ( Num e,
386+ ConstructableN cols rows,
387+ EnumerableN cols
388+ )
416− => e -> Matrix e cols rows
389+ => e -> Matrix e cols rows
417constant = M . I.constant
390constant = M . I.constant
418
391
419-- Bang Matrix
392-- Bang Matrix
420
393
421-- | The T (Top) row vector matrix.
394-- | The T (Top) row vector matrix.
422bang ::
395bang ::
423− forall e cols.
396+ ( Num e,
424− (Num e, Enum e, FromListsN e cols (), CountableN cols) =>
397+ ConstructN cols,
398+ EnumerableN cols
399+ )
425− Matrix e cols One
400+ => Matrix e cols One
426−bang = M I.bang
401+bang = ones
427−
402+
428−-- | Point constant relation
403+-- | Point constant matrix
429−point ::
404+point ::
430− ( Bounded a,
431− Enum a,
432− Eq a,
433− Num e,
405+ ( Num e,
434− Ord e,
406+ Liftable () a
435− CountableN a,
436− FromListsN e a One
437 ) => a -> Matrix e One a
407 ) => a -> Matrix e One a
438point = fromF . const
408point = fromF . const
439
409
@@ -441,8 +411,12 @@ point = fromF . const
441
411
442-- | iden matrix
412-- | iden matrix
443iden ::
413iden ::
444− (Num e, FromListsN e a a, CountableN a) =>
414+ ( Num e,
415+ EqN a,
416+ ConstructN a,
417+ EnumerableN a
418+ )
445− Matrix e a a
419+ => Matrix e a a
446iden = M I.iden
420iden = M I.iden
447{-# NOINLINE iden #-}
421{-# NOINLINE iden #-}
448
422
@@ -476,44 +450,48 @@ infixl 7 ./
476
450
477-- | Biproduct first component projection
451-- | Biproduct first component projection
478p1 ::
452p1 ::
479− ( Num e,
453+ ( Num e,
480− CountableDimensionsN n m,
454+ EqN m,
481− FromListsN e n m,
455+ ConstructableN m n,
482− FromListsN e m m
456+ EnumerableN m,
457+ EnumerableN n
483− ) =>
458+ )
484− Matrix e (Either m n) m
459+ => Matrix e (Either m n) m
485p1 = M I.p1
460p1 = M I.p1
486
461
487-- | Biproduct second component projection
462-- | Biproduct second component projection
488p2 ::
463p2 ::
489− ( Num e,
464+ ( Num e,
490− CountableDimensionsN n m,
465+ EqN n,
491− FromListsN e m n,
466+ ConstructableN m n,
492− FromListsN e n n
467+ EnumerableN m,
468+ EnumerableN n
493− ) =>
469+ )
494− Matrix e (Either m n) n
470+ => Matrix e (Either m n) n
495p2 = M I.p2
471p2 = M I.p2
496
472
497-- Injections
473-- Injections
498
474
499-- | Biproduct first component injection
475-- | Biproduct first component injection
500i1 ::
476i1 ::
501− ( Num e,
477+ ( Num e,
502− CountableDimensionsN n m,
478+ EqN m,
503− FromListsN e n m,
479+ ConstructableN m n,
504− FromListsN e m m
480+ EnumerableN m,
481+ EnumerableN n
505− ) =>
482+ )
506− Matrix e m (Either m n)
483+ => Matrix e m (Either m n)
507i1 = tr p1
484i1 = tr p1
508
485
509-- | Biproduct second component injection
486-- | Biproduct second component injection
510i2 ::
487i2 ::
511− ( Num e,
488+ ( Num e,
512− CountableDimensionsN n m,
489+ EqN n,
513− FromListsN e m n,
490+ ConstructableN m n,
514− FromListsN e n n
491+ EnumerableN m,
492+ EnumerableN n
515− ) =>
493+ )
516− Matrix e n (Either m n)
494+ => Matrix e n (Either m n)
517i2 = tr p2
495i2 = tr p2
518
496
519-- Dimensions
497-- Dimensions
@@ -525,7 +503,7 @@ i2 = tr p2
525--
503--
526-- TODO: A 'rows' function that does not need the 'KnownNat' constraint in
504-- TODO: A 'rows' function that does not need the 'KnownNat' constraint in
527-- exchange for performance.
505-- exchange for performance.
528−rows :: (CountableN rows) => Matrix e cols rows -> Int
506+rows :: CountableN rows => Matrix e cols rows -> Int
529rows (M m) = I.rows m
507rows (M m) = I.rows m
530
508
531-- | Obtain the number of columns.
509-- | Obtain the number of columns.
@@ -535,7 +513,7 @@ rows (M m) = I.rows m
535--
513--
536-- TODO: A 'columns' function that does not need the 'KnownNat' constraint in
514-- TODO: A 'columns' function that does not need the 'KnownNat' constraint in
537-- exchange for performance.
515-- exchange for performance.
538−columns :: (CountableN cols) => Matrix e cols rows -> Int
516+columns :: CountableN cols => Matrix e cols rows -> Int
539columns (M m) = I.columns m
517columns (M m) = I.columns m
540
518
541-- Coproduct Bifunctor
519-- Coproduct Bifunctor
@@ -544,41 +522,53 @@ infixl 5 -|-
544
522
545-- | Matrix coproduct functor also known as matrix direct sum.
523-- | Matrix coproduct functor also known as matrix direct sum.
546(-|-) ::
524(-|-) ::
547− ( Num e,
525+ ( Num e,
548− CountableDimensionsN j k,
526+ EqN k,
549− FromListsN e k k,
527+ EqN j,
550− FromListsN e j k,
528+ ConstructableN k j,
551− FromListsN e k j,
529+ EnumerableN k,
552− FromListsN e j j
530+ EnumerableN j
553− ) =>
554− Matrix e n k ->
555− Matrix e m j ->
556− Matrix e (Either n m) (Either k j)
531+ ) => Matrix e n k -> Matrix e m j -> Matrix e (Either n m) (Either k j)
557(-|-) (M a) (M b) = M ((I.-|-) a b)
532(-|-) (M a) (M b) = M ((I.-|-) a b)
558
533
559-- Khatri Rao Product and projections
534-- Khatri Rao Product and projections
560
535
561−-- | Khatri Rao product first component projection matrix.
536+type FstM a b =
562−fstM ::
537+ ( EqN a,
563− forall e m k .
538+ ConstructableN (I.Normalize a) (I.Normalize (a, b)),
564− ( Num e,
539+ ConstructN (I.Normalize a, I.Normalize b),
565− CountableDimensionsN m k,
540+ EnumerableN a,
566− CountableN (m, k),
541+ EnumerableN b,
567− FromListsN e (m, k) m,
542+ EnumN (I.Normalize a, I.Normalize b),
568− TrivialP m k
543+ Trivial2 a,
569− ) => Matrix e (m, k) m
544+ TrivialP a b
570−fstM = M (I.fstM @e @(I.Normalize m) @(I.Normalize k))
545+ )
571
546
547+-- | Khatri Rao product first component projection matrix.
548+fstM ::
549+ forall e a b .
550+ ( Num e,
551+ FstM a b
552+ ) => Matrix e (a, b) a
553+fstM = M (I.fstM @e @(I.Normalize a) @(I.Normalize b))
554+
555+type SndM a b =
556+ ( EqN b,
557+ ConstructableN (I.Normalize b) (I.Normalize (a, b)),
558+ ConstructN (I.Normalize a, I.Normalize b),
559+ EnumerableN a,
560+ EnumerableN b,
561+ EnumN (I.Normalize a, I.Normalize b),
562+ Trivial2 b,
563+ TrivialP a b
564+ )
572-- | Khatri Rao product second component projection matrix.
565-- | Khatri Rao product second component projection matrix.
573−sndM ::
566+sndM ::
574− forall e m k.
567+ forall e a b.
575− ( Num e,
568+ ( Num e,
576− CountableDimensionsN k m,
569+ SndM a b
577− CountableN (m, k),
578− FromListsN e (m, k) k,
579− TrivialP m k
580− ) => Matrix e (m, k) k
570+ ) => Matrix e (a, b) b
581−sndM = M (I.sndM @e @(I.Normalize m) @(I.Normalize k))
571+sndM = M (I.sndM @e @(I.Normalize a) @(I.Normalize b))
582
572
583-- | Khatri Rao Matrix product also known as matrix pairing.
573-- | Khatri Rao Matrix product also known as matrix pairing.
584--
574--
@@ -592,14 +582,12 @@ sndM = M (I.sndM @e @(I.Normalize m) @(I.Normalize k))
592--
582--
593-- __Emphasis__ on the implication symbol.
583-- __Emphasis__ on the implication symbol.
594kr ::
584kr ::
595− forall e cols a b.
585+ forall e cols a b.
596− ( Num e,
586+ ( Num e,
597− CountableDimensionsN a b,
587+ FstM a b,
598− CountableN (a, b),
588+ SndM a b
599− FromListsN e (a, b) a,
589+ )
600− FromListsN e (a, b) b,
601− TrivialP a b
602− ) => Matrix e cols a -> Matrix e cols b -> Matrix e cols (a, b)
590+ => Matrix e cols a -> Matrix e cols b -> Matrix e cols (a, b)
603kr a b =
591kr a b =
604 let fstM' = fstM @e @a @b
592 let fstM' = fstM @e @a @b
605 sndM' = sndM @e @a @b
593 sndM' = sndM @e @a @b
@@ -608,21 +596,38 @@ kr a b =
608-- Product Bifunctor (Kronecker)
596-- Product Bifunctor (Kronecker)
609
597
610infixl 4 ><
598infixl 4 ><
599+type Kronecker m n p q =
600+ ( EqN (I.Normalize m),
601+ EqN (I.Normalize n),
602+ EqN (I.Normalize p),
603+ EqN (I.Normalize q),
604+ ConstructableN (I.Normalize m) (I.Normalize n),
605+ ConstructableN (I.Normalize p) (I.Normalize q),
606+ ConstructableN (I.Normalize m, I.Normalize n) (I.Normalize p, I.Normalize q),
607+ ConstructableN (I.Normalize (I.Normalize m, I.Normalize n)) (I.Normalize (I.Normalize p, I.Normalize q)),
608+ FstM m n,
609+ SndM m n,
610+ EnumerableN (I.Normalize m),
611+ EnumerableN (I.Normalize n),
612+ EnumerableN (I.Normalize p),
613+ EnumerableN (I.Normalize q),
614+ EnumerableN (I.Normalize m, I.Normalize n),
615+ EnumerableN (I.Normalize p, I.Normalize q),
616+ Trivial2 m,
617+ Trivial2 n,
618+ Trivial2 p,
619+ Trivial2 q,
620+ TrivialP p q,
621+ TrivialP m m
622+ )
611
623
612-- | Matrix product functor also known as Kronecker product
624-- | Matrix product functor also known as Kronecker product
613(><) ::
625(><) ::
614− forall e m p n q.
626+ forall e m p n q.
615− ( Num e,
627+ ( Num e,
616− CountableDimensionsN m n,
628+ Kronecker m n p q
617− CountableDimensionsN p q,
629+ )
618− CountableDimensionsN (m, n) (p, q),
619− FromListsN e (m, n) m,
620− FromListsN e (m, n) n,
621− FromListsN e (p, q) p,
622− FromListsN e (p, q) q,
623− TrivialP m n,
624− TrivialP p q
625− ) => Matrix e m p -> Matrix e n q -> Matrix e (m, n) (p, q)
630+ => Matrix e m p -> Matrix e n q -> Matrix e (m, n) (p, q)
626(><) a b =
631(><) a b =
627 let fstM' = fstM @e @m @n
632 let fstM' = fstM @e @m @n
628 sndM' = sndM @e @m @n
633 sndM' = sndM @e @m @n
@@ -662,34 +667,23 @@ tr (M m) = M (I.tr m)
662
667
663-- | Selective functors 'select' operator equivalent inspired by the
668-- | Selective functors 'select' operator equivalent inspired by the
664-- ArrowMonad solution presented in the paper.
669-- ArrowMonad solution presented in the paper.
665−selectM ::
666− ( Num e,
667− FromListsN e b b,
668− CountableN b
669− ) => Matrix e cols (Either a b) -> Matrix e a b -> Matrix e cols b
670+selectM :: (Num e, EqN b, ConstructN b, EnumerableN b) => Matrix e cols (Either a b) -> Matrix e a b -> Matrix e cols b
670selectM (M m) (M y) = M (I.select m y)
671selectM (M m) (M y) = M (I.select m y)
671
672
672-- McCarthy's Conditional
673-- McCarthy's Conditional
673
674
674-- | McCarthy's Conditional expresses probabilistic choice.
675-- | McCarthy's Conditional expresses probabilistic choice.
675−cond ::
676+-- cond ::
676− ( Trivial a,
677+-- (
677− Trivial2 a,
678− Trivial3 a,
679− CountableN a,
680− FromListsN e () a,
681− FromListsN e a (),
682− FromListsN e a a,
683− Liftable e a Bool
684− )
678+-- )
685− =>
679+-- =>
686− (a -> Bool) -> Matrix e a b -> Matrix e a b -> Matrix e a b
680+-- (a -> Bool) -> Matrix e a b -> Matrix e a b -> Matrix e a b
687−cond p (M a) (M b) = M (I.cond p a b)
681+-- cond p (M a) (M b) =
688
682
689-- Pretty print
683-- Pretty print
690
684
691-- | Matrix pretty printer
685-- | Matrix pretty printer
692−pretty :: (CountableDimensionsN cols rows, Show e) => Matrix e cols rows -> String
686+pretty :: (Show e, CountableDimensionsN cols rows) => Matrix e cols rows -> String
693pretty (M m) = I.pretty m
687pretty (M m) = I.pretty m
694
688
695-- | Matrix pretty printer
689-- | Matrix pretty printer