@@ -1,15 +1,15 @@
1{-# LANGUAGE AllowAmbiguousTypes #-}
1{-# LANGUAGE AllowAmbiguousTypes #-}
2{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE DerivingVia #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE GADTs #-}
6{-# LANGUAGE GADTs #-}
6−{-# LANGUAGE InstanceSigs #-}
7+{-# LANGUAGE KindSignatures #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE NoStarIsType #-}
9{-# LANGUAGE NoStarIsType #-}
10+{-# LANGUAGE RankNTypes #-}
9{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE ScopedTypeVariables #-}
10−{-# LANGUAGE StandaloneDeriving #-}
11{-# LANGUAGE TypeApplications #-}
12{-# LANGUAGE TypeApplications #-}
12−{-# LANGUAGE TypeFamilies #-}
13{-# LANGUAGE TypeOperators #-}
13{-# LANGUAGE TypeOperators #-}
14{-# LANGUAGE UndecidableInstances #-}
14{-# LANGUAGE UndecidableInstances #-}
@@ -27,24 +27,38 @@
27-- in Haskell. See <https://github.com/bolt12/master-thesis my Msc Thesis> for the
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.
28-- motivation behind the library, the underlying theory, and implementation details.
30−-- This module offers many of the combinators mentioned in the work of
30+-- This module offers a newtype wrapper around 'Matrix.Type.Matrix' that
31−-- Macedo (2012) and Oliveira (2012).
31+-- uses arbitrary types instead of canonical data types for the matrices
34+-- __NOTE__: If the types in the dimensions are custom they must need to
35+-- implement a 'Generic' instance.
33-----------------------------------------------------------------------------
37-----------------------------------------------------------------------------
35module Matrix.Type
39module Matrix.Type
36− ( -- | This definition makes use of the fact that 'Void' is
40+ ( -- | LAoP (Linear Algebra of Programming) Inductive Matrix definition.
37− -- isomorphic to 0 and '()' to 1 and captures matrix
41+ --
38− -- dimensions as stacks of 'Either's.
42+ -- LAoP generalises relations and functions treating them as
43+ -- Boolean matrices and in turn consider these as arrows.
44+ -- This library offers many of the combinators mentioned in the work of
45+ -- Macedo (2012) and Oliveira (2012).
47+ -- This definition is a wrapper around 'Matrix.Type' but
48+ -- dimensions are arbitrary data types. Type inference might not
51+ -- __NOTE__: If the types in the dimensions are custom they must need to
52+ -- implement a 'Generic' instance.
40− -- There exists two type families that make it easier to write
41− -- matrix dimensions: 'FromNat' and 'Count'. This approach
42− -- leads to a very straightforward implementation
43− -- of LAoP combinators.
45 -- * Type safe matrix representation
55 -- * Type safe matrix representation
46 Matrix (..),
56 Matrix (..),
48 -- * Primitives
62 -- * Primitives
@@ -52,12 +66,12 @@ module Matrix.Type
54 -- * Auxiliary type families
68 -- * Auxiliary type families
55− FromNat,
69+ I.FromNat,
57− Normalize,
71+ I.Normalize,
59 -- * Matrix construction and conversion
73 -- * Matrix construction and conversion
60− FromLists,
74+ I.FromLists,
61 fromLists,
75 fromLists,
@@ -128,214 +142,106 @@ module Matrix.Type
129 prettyPrint
143 prettyPrint
138import Data.Void
147import Data.Void
139−import GHC.TypeLits
150+import GHC.TypeLits
140−import Data.Type.Equality
142import Control.DeepSeq
151import Control.DeepSeq
152+import qualified Control.Category as C
153+import qualified Matrix.Internal as I
144−-- | LAoP (Linear Algebra of Programming) Inductive Matrix definition.
155+newtype Matrix e (cols :: Type) (rows :: Type) = M (I.Matrix e (I.Normalize cols) (I.Normalize rows))
145−data Matrix e cols rows where
146− Empty :: Matrix e Void Void
147− One :: e -> Matrix e () ()
148− Junc :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
149− Split :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
151−deriving instance (Show e) => Show (Matrix e cols rows)
156+ deriving (Show, Num, Eq, NFData) via (I.Matrix e (I.Normalize cols) (I.Normalize rows))
153−-- | Type family that computes the cardinality of a given type dimension.
158+-- | It isn't possible to implement the 'id' function so it's
154−-- It can also count the cardinality of custom types that implement the
159+-- implementation is 'undefined'. However 'comp' can be and this partial
155−-- 'Generic' instance.
160+-- class implementation exists just to make the code more readable.
156−type family Count (d :: Type) where
161+--
157− Count (Natural n m) = (m - n) + 1
162+-- Please use 'identity' instead.
158− Count (Either a b) = (+) (Count a) (Count b)
163+instance (Num e) => C.Category (Matrix e) where
159− Count (a, b) = (*) (Count a) (Count b)
164+ id = undefined
160− Count (a -> b) = (^) (Count b) (Count a)
165+ (.) = comp
162− Count (M1 _ _ f p) = Count (f p)
167+-- | Zero type alias
163− Count (K1 _ _ _) = 1
168+type Zero = Void
164− Count (V1 _) = 0
169+
165− Count (U1 _) = 1
170+-- | One type alias
166− Count ((:*:) a b p) = Count (a p) * Count (b p)
171+type One = ()
167− Count ((:+:) a b p) = Count (a p) + Count (b p)
168− Count d = Count (Rep d R)
170−-- | Type family that computes of a given type dimension from a given natural
171−-- Thanks to Li-Yao Xia this type family is super fast.
172−type family FromNat (n :: Nat) where
175− FromNat n = FromNat' (Mod n 2 == 0) (FromNat (Div n 2))
177−type family FromNat' (b :: Bool) (m :: Type) :: Type where
178− FromNat' 'True m = Either m m
179− FromNat' 'False m = Either () (Either m m)
181−-- | Type family that normalizes the representation of a given data
183−type family Normalize (d :: Type) where
184− Normalize d = FromNat (Count d)
186−instance NFData e => NFData (Matrix e cols rows) where
189− rnf (Junc a b) = rnf a `seq` rnf b
190− rnf (Split a b) = rnf a `seq` rnf b
192−instance Eq e => Eq (Matrix e cols rows) where
193− Empty == Empty = True
194− (One a) == (One b) = a == b
195− (Junc a b) == (Junc c d) = a == c && b == d
196− (Split a b) == (Split c d) = a == c && b == d
197− x@(Split a b) == y@(Junc c d) = x == abideJS y
198− x@(Junc a b) == y@(Split c d) = abideJS x == y
200−instance Num e => Num (Matrix e cols rows) where
202− Empty + Empty = Empty
203− (One a) + (One b) = One (a + b)
204− (Junc a b) + (Junc c d) = Junc (a + c) (b + d)
205− (Split a b) + (Split c d) = Split (a + c) (b + d)
206− x@(Split a b) + y@(Junc c d) = x + abideJS y
207− x@(Junc a b) + y@(Split c d) = abideJS x + y
209− Empty - Empty = Empty
210− (One a) - (One b) = One (a - b)
211− (Junc a b) - (Junc c d) = Junc (a - c) (b - d)
212− (Split a b) - (Split c d) = Split (a - c) (b - d)
213− x@(Split a b) - y@(Junc c d) = x - abideJS y
214− x@(Junc a b) - y@(Split c d) = abideJS x - y
216− Empty * Empty = Empty
217− (One a) * (One b) = One (a * b)
218− (Junc a b) * (Junc c d) = Junc (a * c) (b * d)
219− (Split a b) * (Split c d) = Split (a * c) (b * d)
220− x@(Split a b) * y@(Junc c d) = x * abideJS y
221− x@(Junc a b) * y@(Split c d) = abideJS x * y
224− abs (One a) = One (abs a)
225− abs (Junc a b) = Junc (abs a) (abs b)
226− abs (Split a b) = Split (abs a) (abs b)
228− signum Empty = Empty
229− signum (One a) = One (signum a)
230− signum (Junc a b) = Junc (signum a) (signum b)
231− signum (Split a b) = Split (signum a) (signum b)
233-- Primitives
173-- Primitives
235-- | Empty matrix constructor
175-- | Empty matrix constructor
236−empty :: Matrix e Void Void
176+empty :: Matrix e Zero Zero
237−empty = Empty
177+empty = M I.Empty
239-- | Unit matrix constructor
179-- | Unit matrix constructor
240−one :: e -> Matrix e () ()
180+one :: e -> Matrix e One One
241−one = One
181+one = M . I.One
243-- | Matrix 'Junc' constructor
183-- | Matrix 'Junc' constructor
185+ (I.Normalize (Either a b) ~ Either (I.Normalize a) (I.Normalize b)) =>
244−junc :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
188+ Matrix e (Either a b) rows
245−junc = Junc
189+junc (M a) (M b) = M (I.Junc a b)
247infixl 3 |||
191infixl 3 |||
249-- | Matrix 'Junc' constructor
192-- | Matrix 'Junc' constructor
194+ (I.Normalize (Either a b) ~ Either (I.Normalize a) (I.Normalize b)) =>
250−(|||) :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
197+ Matrix e (Either a b) rows
251−(|||) = Junc
198+(|||) = junc
253-- | Matrix 'Split' constructor
200-- | Matrix 'Split' constructor
202+ (I.Normalize (Either a b) ~ Either (I.Normalize a) (I.Normalize b)) =>
254−split :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
205+ Matrix e cols (Either a b)
255−split = Split
206+split (M a) (M b) = M (I.Split a b)
257infixl 2 ===
208infixl 2 ===
259-- | Matrix 'Split' constructor
209-- | Matrix 'Split' constructor
211+ (I.Normalize (Either a b) ~ Either (I.Normalize a) (I.Normalize b)) =>
260−(===) :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
214+ Matrix e cols (Either a b)
261−(===) = Split
215+(===) = split
263-- Construction
217-- Construction
265−-- | Type class for defining the 'fromList' conversion function.
266−-- Given that it is not possible to branch on types at the term level type
267−-- classes are needed bery much like an inductive definition but on types.
268−class FromLists e cols rows where
269− -- | Build a matrix out of a list of list of elements. Throws a runtime
219+-- | Build a matrix out of a list of list of elements. Throws a runtime
270− -- error if the dimensions do not match.
220+-- error if the dimensions do not match.
271− fromLists :: [[e]] -> Matrix e cols rows
221+fromLists :: (I.FromLists e (I.Normalize cols) (I.Normalize rows)) => [[e]] -> Matrix e cols rows
273−instance FromLists e Void Void where
274− fromLists [] = Empty
222+fromLists = M . I.fromLists
275− fromLists _ = error "Wrong dimensions"
277−instance {-# OVERLAPPING #-} FromLists e () () where
278− fromLists [[e]] = One e
279− fromLists _ = error "Wrong dimensions"
281−instance {-# OVERLAPPING #-} (FromLists e cols ()) => FromLists e (Either () cols) () where
282− fromLists [h : t] = Junc (One h) (fromLists [t])
283− fromLists _ = error "Wrong dimensions"
285−instance {-# OVERLAPPABLE #-} (FromLists e a (), FromLists e b (), KnownNat (Count a)) => FromLists e (Either a b) () where
287− let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
288− in Junc (fromLists [take rowsA l]) (fromLists [drop rowsA l])
289− fromLists _ = error "Wrong dimensions"
291−instance {-# OVERLAPPING #-} (FromLists e () rows) => FromLists e () (Either () rows) where
292− fromLists ([h] : t) = Split (One h) (fromLists t)
293− fromLists _ = error "Wrong dimensions"
295−instance {-# OVERLAPPABLE #-} (FromLists e () a, FromLists e () b, KnownNat (Count a)) => FromLists e () (Either a b) where
296− fromLists l@([h] : t) =
297− let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
298− in Split (fromLists (take rowsA l)) (fromLists (drop rowsA l))
299− fromLists _ = error "Wrong dimensions"
301−instance {-# OVERLAPPABLE #-} (FromLists e (Either a b) c, FromLists e (Either a b) d, KnownNat (Count c)) => FromLists e (Either a b) (Either c d) where
302− fromLists l@(h : t) =
304− rowsC = fromInteger (natVal (Proxy :: Proxy (Count c)))
305− condition = all (== lh) (map length t)
306− in if lh > 0 && condition
307− then Split (fromLists (take rowsC l)) (fromLists (drop rowsC l))
308− else error "Not all rows have the same length"
310-- | Matrix builder function. Constructs a matrix provided with
224-- | Matrix builder function. Constructs a matrix provided with
311-- a construction function.
225-- a construction function.
312matrixBuilder ::
226matrixBuilder ::
313− forall e cols rows.
227+ (I.FromLists e (I.Normalize cols) (I.Normalize rows), KnownNat (I.Count (I.Normalize cols)), KnownNat (I.Count (I.Normalize rows))) =>
314− ( FromLists e cols rows,
315− KnownNat (Count cols),
316− KnownNat (Count rows)
318 ((Int, Int) -> e) ->
228 ((Int, Int) -> e) ->
319 Matrix e cols rows
229 Matrix e cols rows
320−matrixBuilder f =
230+matrixBuilder = M . I.matrixBuilder
321− let c = fromInteger $ natVal (Proxy :: Proxy (Count cols))
322− r = fromInteger $ natVal (Proxy :: Proxy (Count rows))
323− positions = [(a, b) | a <- [0 .. (r - 1)], b <- [0 .. (c - 1)]]
324− in fromLists . map (map f) . groupBy (\(x, _) (w, _) -> x == w) $ positions
326-- | Constructs a column vector matrix
232-- | Constructs a column vector matrix
327−col :: (FromLists e () rows) => [e] -> Matrix e () rows
233+col :: (I.FromLists e () (I.Normalize rows)) => [e] -> Matrix e One rows
328−col = fromLists . map (: [])
234+col = M . I.col
330-- | Constructs a row vector matrix
236-- | Constructs a row vector matrix
331−row :: (FromLists e cols ()) => [e] -> Matrix e cols ()
237+row :: (I.FromLists e (I.Normalize cols) ()) => [e] -> Matrix e cols One
332−row = fromLists . (: [])
238+row = M . I.row
334-- | Lifts functions to matrices with arbitrary dimensions.
240-- | Lifts functions to matrices with arbitrary dimensions.
335−-- NOTE: Be careful to not ask for a matrix bigger than the cardinality of
242+-- NOTE: Be careful to not ask for a matrix bigger than the cardinality of
336-- types @a@ or @b@ allows.
243-- types @a@ or @b@ allows.
338− forall a b cols rows e.
339 ( Bounded a,
245 ( Bounded a,
340 Bounded b,
246 Bounded b,
@@ -343,35 +249,17 @@ fromF ::
346− KnownNat (Count cols),
252+ KnownNat (I.Count (I.Normalize cols)),
347− KnownNat (Count rows),
253+ KnownNat (I.Count (I.Normalize rows)),
348− FromLists e rows cols
254+ I.FromLists e (I.Normalize rows) (I.Normalize cols)
350 (a -> b) ->
256 (a -> b) ->
351 Matrix e cols rows
257 Matrix e cols rows
352−fromF f =
258+fromF = M . I.fromF
353− let minA = minBound @a
357− ccols = fromInteger $ natVal (Proxy :: Proxy (Count cols))
358− rrows = fromInteger $ natVal (Proxy :: Proxy (Count rows))
359− elementsA = take ccols [minA .. maxA]
360− elementsB = take rrows [minB .. maxB]
361− combinations = (,) <$> elementsA <*> elementsB
362− combAp = map snd . sort . map (\(a, b) -> if f a == b
363− then ((fromEnum a, fromEnum b), 1)
364− else ((fromEnum a, fromEnum b), 0)) $ combinations
365− mList = buildList combAp rrows
366− in tr $ fromLists mList
369− buildList l r = take r l : buildList (drop r l) r
371-- | Lifts functions to matrices with dimensions matching @a@ and @b@
260-- | Lifts functions to matrices with dimensions matching @a@ and @b@
372-- cardinality's.
261-- cardinality's.
375 ( Bounded a,
263 ( Bounded a,
376 Bounded b,
264 Bounded b,
@@ -379,133 +267,149 @@ fromF' ::
382− KnownNat (Count (Normalize a)),
270+ KnownNat (I.Count (I.Normalize a)),
383− KnownNat (Count (Normalize b)),
271+ KnownNat (I.Count (I.Normalize b)),
384− FromLists e (Normalize b) (Normalize a)
272+ I.FromLists e (I.Normalize b) (I.Normalize a)
386 (a -> b) ->
274 (a -> b) ->
387− Matrix e (Normalize a) (Normalize b)
275+ Matrix e a b
388−fromF' f =
276+fromF' = M . I.fromF'
389− let minA = minBound @a
393− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
394− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
395− elementsA = take ccols [minA .. maxA]
396− elementsB = take rrows [minB .. maxB]
397− combinations = (,) <$> elementsA <*> elementsB
398− combAp = map snd . sort . map (\(a, b) -> if f a == b
399− then ((fromEnum a, fromEnum b), 1)
400− else ((fromEnum a, fromEnum b), 0)) $ combinations
401− mList = buildList combAp rrows
402− in tr $ fromLists mList
405− buildList l r = take r l : buildList (drop r l) r
407-- Conversion
278-- Conversion
409-- | Converts a matrix to a list of lists of elements.
280-- | Converts a matrix to a list of lists of elements.
410toLists :: Matrix e cols rows -> [[e]]
281toLists :: Matrix e cols rows -> [[e]]
411−toLists Empty = []
282+toLists (M m) = I.toLists m
412−toLists (One e) = [[e]]
413−toLists (Split l r) = toLists l ++ toLists r
414−toLists (Junc l r) = zipWith (++) (toLists l) (toLists r)
416-- | Converts a matrix to a list of elements.
284-- | Converts a matrix to a list of elements.
417toList :: Matrix e cols rows -> [e]
285toList :: Matrix e cols rows -> [e]
418−toList = concat . toLists
286+toList (M m) = I.toList m
420-- Zeros Matrix
288-- Zeros Matrix
422-- | The zero matrix. A matrix wholly filled with zeros.
290-- | The zero matrix. A matrix wholly filled with zeros.
423−zeros :: (Num e, FromLists e cols rows, KnownNat (Count cols), KnownNat (Count rows)) => Matrix e cols rows
292+ (Num e, I.FromLists e (I.Normalize cols) (I.Normalize rows), KnownNat (I.Count (I.Normalize cols)), KnownNat (I.Count (I.Normalize rows))) =>
424−zeros = matrixBuilder (const 0)
293+ Matrix e cols rows
426-- Ones Matrix
296-- Ones Matrix
428-- | The ones matrix. A matrix wholly filled with ones.
298-- | The ones matrix. A matrix wholly filled with ones.
429−-- Also known as T (Top) matrix.
300+-- Also known as T (Top) matrix.
430−ones :: (Num e, FromLists e cols rows, KnownNat (Count cols), KnownNat (Count rows)) => Matrix e cols rows
302+ (Num e, I.FromLists e (I.Normalize cols) (I.Normalize rows), KnownNat (I.Count (I.Normalize cols)), KnownNat (I.Count (I.Normalize rows))) =>
431−ones = matrixBuilder (const 1)
303+ Matrix e cols rows
433-- Const Matrix
306-- Const Matrix
435-- | The constant matrix constructor. A matrix wholly filled with a given
308-- | The constant matrix constructor. A matrix wholly filled with a given
437−constant :: (Num e, FromLists e cols rows, KnownNat (Count cols), KnownNat (Count rows)) => e -> Matrix e cols rows
311+ (Num e, I.FromLists e (I.Normalize cols) (I.Normalize rows), KnownNat (I.Count (I.Normalize cols)), KnownNat (I.Count (I.Normalize rows))) =>
438−constant e = matrixBuilder (const e)
312+ e ->
314+constant = M . I.constant
440-- Bang Matrix
316-- Bang Matrix
442-- | The T (Top) row vector matrix.
318-- | The T (Top) row vector matrix.
443−bang :: forall e cols. (Num e, Enum e, FromLists e cols (), KnownNat (Count cols)) => Matrix e cols ()
321+ (Num e, Enum e, I.FromLists e (I.Normalize cols) (), KnownNat (I.Count (I.Normalize cols))) =>
444−bang =
323+bang = M I.bang
445− let c = fromInteger $ natVal (Proxy :: Proxy (Count cols))
446− in fromLists [take c [1, 1 ..]]
448-- Identity Matrix
325-- Identity Matrix
450−-- | Identity matrix.
327+-- | Identity matrix
451−identity :: (Num e, FromLists e cols cols, KnownNat (Count cols)) => Matrix e cols cols
329+ (Num e, I.FromLists e (I.Normalize a) (I.Normalize a), KnownNat (I.Count (I.Normalize a))) =>
452−identity = matrixBuilder (bool 0 1 . uncurry (==))
330+ Matrix e a a
331+identity = M I.identity
454-- Matrix composition (MMM)
333-- Matrix composition (MMM)
456-- | Matrix composition. Equivalent to matrix-matrix multiplication.
335-- | Matrix composition. Equivalent to matrix-matrix multiplication.
457−-- This definition takes advantage of divide-and-conquer and fusion laws
337+-- This definition takes advantage of divide-and-conquer and fusion laws
458-- from LAoP.
338-- from LAoP.
459comp :: (Num e) => Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
339comp :: (Num e) => Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
460−comp Empty Empty = Empty
340+comp (M a) (M b) = M (I.comp a b)
461−comp (One a) (One b) = One (a * b)
462−comp (Junc a b) (Split c d) = comp a c + comp b d -- Divide-and-conquer law
463−comp (Split a b) c = Split (comp a c) (comp b c) -- Split fusion law
464−comp c (Junc a b) = Junc (comp c a) (comp c b) -- Junc fusion law
468-- | Biproduct first component projection
342-- | Biproduct first component projection
469−p1 :: 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
343+p1 ::
345+ KnownNat (I.Count (I.Normalize n)),
346+ KnownNat (I.Count (I.Normalize m)),
347+ I.FromLists e (I.Normalize n) (I.Normalize m),
348+ I.FromLists e (I.Normalize m) (I.Normalize m),
349+ I.Normalize (Either m n) ~ Either (I.Normalize m) (I.Normalize n)
351+ Matrix e (Either m n) m
471− let iden = identity :: Matrix e m m
472− zero = zeros :: Matrix e n m
475-- | Biproduct second component projection
354-- | Biproduct second component projection
476−p2 :: 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
355+p2 ::
357+ KnownNat (I.Count (I.Normalize n)),
358+ KnownNat (I.Count (I.Normalize m)),
359+ I.FromLists e (I.Normalize m) (I.Normalize n),
360+ I.FromLists e (I.Normalize n) (I.Normalize n),
361+ I.Normalize (Either m n) ~ Either (I.Normalize m) (I.Normalize n)
363+ Matrix e (Either m n) n
478− let iden = identity :: Matrix e n n
479− zero = zeros :: Matrix e m n
482-- Injections
366-- Injections
484-- | Biproduct first component injection
368-- | Biproduct first component injection
485−i1 :: (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e n m, FromLists e m m) => Matrix e m (Either m n)
369+i1 ::
371+ KnownNat (I.Count (I.Normalize n)),
372+ KnownNat (I.Count (I.Normalize m)),
373+ I.FromLists e (I.Normalize n) (I.Normalize m),
374+ I.FromLists e (I.Normalize m) (I.Normalize m),
375+ I.Normalize (Either m n) ~ Either (I.Normalize m) (I.Normalize n)
377+ Matrix e m (Either m n)
486i1 = tr p1
378i1 = tr p1
488-- | Biproduct second component injection
380-- | Biproduct second component injection
489−i2 :: (Num e, KnownNat (Count n), KnownNat (Count m), FromLists e m n, FromLists e n n) => Matrix e n (Either m n)
381+i2 ::
383+ KnownNat (I.Count (I.Normalize n)),
384+ KnownNat (I.Count (I.Normalize m)),
385+ I.FromLists e (I.Normalize m) (I.Normalize n),
386+ I.FromLists e (I.Normalize n) (I.Normalize n),
387+ I.Normalize (Either m n) ~ Either (I.Normalize m) (I.Normalize n)
389+ Matrix e n (Either m n)
490i2 = tr p2
390i2 = tr p2
492-- Dimensions
392-- Dimensions
494-- | Obtain the number of rows.
394-- | Obtain the number of rows.
495−-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
396+-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
496-- dimensions in constant time.
397-- dimensions in constant time.
497-- TODO: A 'rows' function that does not need the 'KnownNat' constraint in
399-- TODO: A 'rows' function that does not need the 'KnownNat' constraint in
498-- exchange for performance.
400-- exchange for performance.
499−rows :: forall e cols rows. (KnownNat (Count rows)) => Matrix e cols rows -> Int
401+rows :: (KnownNat (I.Count (I.Normalize rows))) => Matrix e cols rows -> Int
500−rows _ = fromInteger $ natVal (Proxy :: Proxy (Count rows))
402+rows (M m) = I.rows m
502-- | Obtain the number of columns.
404-- | Obtain the number of columns.
503−-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
406+-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
504-- dimensions in constant time.
407-- dimensions in constant time.
505-- TODO: A 'columns' function that does not need the 'KnownNat' constraint in
409-- TODO: A 'columns' function that does not need the 'KnownNat' constraint in
506-- exchange for performance.
410-- exchange for performance.
507−columns :: forall e cols rows. (KnownNat (Count cols)) => Matrix e cols rows -> Int
411+columns :: (KnownNat (I.Count (I.Normalize cols))) => Matrix e cols rows -> Int
508−columns _ = fromInteger $ natVal (Proxy :: Proxy (Count cols))
412+columns (M m) = I.columns m
510-- Coproduct Bifunctor
414-- Coproduct Bifunctor
@@ -513,19 +417,20 @@ infixl 5 -|-
514-- | Matrix coproduct functor also known as matrix direct sum.
418-- | Matrix coproduct functor also known as matrix direct sum.
518− KnownNat (Count j),
421+ KnownNat (I.Count (I.Normalize j)),
519− KnownNat (Count k),
422+ KnownNat (I.Count (I.Normalize k)),
520− FromLists e k k,
423+ I.FromLists e (I.Normalize k) (I.Normalize k),
521− FromLists e j k,
424+ I.FromLists e (I.Normalize j) (I.Normalize k),
522− FromLists e k j,
425+ I.FromLists e (I.Normalize k) (I.Normalize j),
523− FromLists e j j
426+ I.FromLists e (I.Normalize j) (I.Normalize j),
427+ I.Normalize (Either n m) ~ Either (I.Normalize n) (I.Normalize m),
428+ I.Normalize (Either k j) ~ Either (I.Normalize k) (I.Normalize j)
525 Matrix e n k ->
430 Matrix e n k ->
526 Matrix e m j ->
431 Matrix e m j ->
527 Matrix e (Either n m) (Either k j)
432 Matrix e (Either n m) (Either k j)
528−(-|-) a b = Junc (comp i1 a) (comp i2 b)
433+(-|-) (M a) (M b) = M ((I.-|-) a b)
530-- Khatri Rao Product and projections
435-- Khatri Rao Product and projections
@@ -533,36 +438,29 @@ infixl 5 -|-
534 forall e m k .
439 forall e m k .
536− KnownNat (Count k),
441+ KnownNat (I.Count (I.Normalize m)),
442+ KnownNat (I.Count (I.Normalize k)),
443+ KnownNat (I.Count (I.Normalize (m, k))),
537− FromLists e (FromNat (Count m * Count k)) m,
444+ I.FromLists e (I.Normalize (m, k)) (I.Normalize m),
538− KnownNat (Count m),
445+ I.Normalize (m, k) ~ I.Normalize (I.Normalize m, I.Normalize k)
539− KnownNat (Count (Normalize (m, k)))
540− ) => Matrix e (Normalize (m, k)) m
446+ ) => Matrix e (m, k) m
541−kp1 = matrixBuilder f
447+kp1 = M (I.kp1 @e @(I.Normalize m) @(I.Normalize k))
543− offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
545− | y >= (x * offset) && y <= (x * offset + offset - 1) = 1
548-- | Khatri Rao product second component projection matrix.
449-- | Khatri Rao product second component projection matrix.
550− forall e m k .
451+ forall e m k.
552− KnownNat (Count k),
453+ KnownNat (I.Count (I.Normalize k)),
454+ KnownNat (I.Count (I.Normalize m)),
455+ KnownNat (I.Count (I.Normalize (m, k))),
553− FromLists e (FromNat (Count m * Count k)) k,
456+ I.FromLists e (I.Normalize (m, k)) (I.Normalize k),
554− KnownNat (Count m),
457+ I.Normalize (m, k) ~ I.Normalize (I.Normalize m, I.Normalize k)
555− KnownNat (Count (Normalize (m, k)))
556− ) => Matrix e (Normalize (m, k)) k
458+ ) => Matrix e (m, k) k
557−kp2 = matrixBuilder f
459+kp2 = M (I.kp2 @e @(I.Normalize m) @(I.Normalize k))
559− offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
561− | x == y || mod (y - x) offset == 0 = 1
564-- | Khatri Rao Matrix product also known as matrix pairing.
461-- | Khatri Rao Matrix product also known as matrix pairing.
565−-- NOTE: That this is not a true categorical product, see for instance:
463+-- NOTE: That this is not a true categorical product, see for instance:
568-- | kp1 `comp` khatri a b == a
466-- | kp1 `comp` khatri a b == a
@@ -571,15 +469,16 @@ kp2 = matrixBuilder f
573-- __Emphasis__ on the implication symbol.
471-- __Emphasis__ on the implication symbol.
574−khatri ::
472+khatri ::
575− forall e cols a b.
473+ forall e cols a b.
576− ( Num e,
474+ ( Num e,
577− KnownNat (Count a),
475+ KnownNat (I.Count (I.Normalize a)),
578− KnownNat (Count b),
476+ KnownNat (I.Count (I.Normalize b)),
579− KnownNat (Count (Normalize (a, b))),
477+ KnownNat (I.Count (I.Normalize (a, b))),
580− FromLists e (Normalize (a, b)) a,
478+ I.FromLists e (I.Normalize (a, b)) (I.Normalize a),
581− FromLists e (Normalize (a, b)) b
479+ I.FromLists e (I.Normalize (a, b)) (I.Normalize b),
480+ I.Normalize (a, b) ~ I.Normalize (I.Normalize a, I.Normalize b)
582− ) => Matrix e cols a -> Matrix e cols b -> Matrix e cols (Normalize (a, b))
481+ ) => Matrix e cols a -> Matrix e cols b -> Matrix e cols (a, b)
583khatri a b =
482khatri a b =
584 let kp1' = kp1 @e @a @b
483 let kp1' = kp1 @e @a @b
585 kp2' = kp2 @e @a @b
484 kp2' = kp2 @e @a @b
@@ -590,21 +489,22 @@ khatri a b =
590infixl 4 ><
489infixl 4 ><
592-- | Matrix product functor also known as kronecker product
491-- | Matrix product functor also known as kronecker product
594− forall e m p n q.
493+ forall e m p n q.
595− ( Num e,
494+ ( Num e,
596− KnownNat (Count m),
495+ KnownNat (I.Count (I.Normalize m)),
597− KnownNat (Count n),
496+ KnownNat (I.Count (I.Normalize n)),
598− KnownNat (Count p),
497+ KnownNat (I.Count (I.Normalize p)),
599− KnownNat (Count q),
498+ KnownNat (I.Count (I.Normalize q)),
600− KnownNat (Count (Normalize (m, n))),
499+ KnownNat (I.Count (I.Normalize (m, n))),
500+ KnownNat (I.Count (I.Normalize (p, q))),
601− FromLists e (Normalize (m, n)) m,
501+ I.FromLists e (I.Normalize (m, n)) (I.Normalize m),
602− FromLists e (Normalize (m, n)) n,
502+ I.FromLists e (I.Normalize (m, n)) (I.Normalize n),
603− KnownNat (Count (Normalize (p, q))),
503+ I.FromLists e (I.Normalize (p, q)) (I.Normalize p),
604− FromLists e (Normalize (p, q)) p,
504+ I.FromLists e (I.Normalize (p, q)) (I.Normalize q),
605− FromLists e (Normalize (p, q)) q
505+ I.Normalize (m, n) ~ I.Normalize (I.Normalize m, I.Normalize n),
606− )
506+ I.Normalize (p, q) ~ I.Normalize (I.Normalize p, I.Normalize q)
607− => Matrix e m p -> Matrix e n q -> Matrix e (Normalize (m, n)) (Normalize (p, q))
507+ ) => Matrix e m p -> Matrix e n q -> Matrix e (m, n) (p, q)
608(><) a b =
508(><) a b =
609 let kp1' = kp1 @e @m @n
509 let kp1' = kp1 @e @m @n
610 kp2' = kp2 @e @m @n
510 kp2' = kp2 @e @m @n
@@ -614,132 +514,78 @@ infixl 4 ><
615-- | Matrix "abiding" followin the 'Junc'-'Split' abide law.
515-- | Matrix "abiding" followin the 'Junc'-'Split' abide law.
618-- 'Junc' ('Split' a c) ('Split' b d) == 'Split' ('Junc' a b) ('Junc' c d)
520-- 'Junc' ('Split' a c) ('Split' b d) == 'Split' ('Junc' a b) ('Junc' c d)
620abideJS :: Matrix e cols rows -> Matrix e cols rows
522abideJS :: Matrix e cols rows -> Matrix e cols rows
621−abideJS (Junc (Split a c) (Split b d)) = Split (Junc (abideJS a) (abideJS b)) (Junc (abideJS c) (abideJS d)) -- Junc-Split abide law
523+abideJS (M m) = M (I.abideJS m)
622−abideJS Empty = Empty
623−abideJS (One e) = One e
624−abideJS (Junc a b) = Junc (abideJS a) (abideJS b)
625−abideJS (Split a b) = Split (abideJS a) (abideJS b)
627-- Matrix abide Split Junc
525-- Matrix abide Split Junc
629-- | Matrix "abiding" followin the 'Split'-'Junc' abide law.
527-- | Matrix "abiding" followin the 'Split'-'Junc' abide law.
632-- 'Split' ('Junc' a b) ('Junc' c d) == 'Junc' ('Split' a c) ('Split' b d)
532-- 'Split' ('Junc' a b) ('Junc' c d) == 'Junc' ('Split' a c) ('Split' b d)
634abideSJ :: Matrix e cols rows -> Matrix e cols rows
534abideSJ :: Matrix e cols rows -> Matrix e cols rows
635−abideSJ (Split (Junc a b) (Junc c d)) = Junc (Split (abideSJ a) (abideSJ c)) (Split (abideSJ b) (abideSJ d)) -- Split-Junc abide law
535+abideSJ (M m) = M (I.abideSJ m)
636−abideSJ Empty = Empty
637−abideSJ (One e) = One e
638−abideSJ (Junc a b) = Junc (abideSJ a) (abideSJ b)
639−abideSJ (Split a b) = Split (abideSJ a) (abideSJ b)
641-- Matrix transposition
537-- Matrix transposition
643-- | Matrix transposition.
539-- | Matrix transposition.
644tr :: Matrix e cols rows -> Matrix e rows cols
540tr :: Matrix e cols rows -> Matrix e rows cols
645−tr Empty = Empty
541+tr (M m) = M (I.tr m)
647−tr (Junc a b) = Split (tr a) (tr b)
648−tr (Split a b) = Junc (tr a) (tr b)
650-- Selective 'select' operator
543-- Selective 'select' operator
652-- | Selective functors 'select' operator equivalent inspired by the
545-- | Selective functors 'select' operator equivalent inspired by the
653-- ArrowMonad solution presented in the paper.
546-- ArrowMonad solution presented in the paper.
654−select :: (Bounded a1, Bounded b, Enum a1, Enum b, Num e, Ord e,
547+select ::
655− KnownNat (Count a2), KnownNat (Count rows), FromLists e rows a2,
548+ ( Bounded a,
656− FromLists e rows rows, Eq b) =>
549+ Bounded b,
555+ KnownNat (I.Count (I.Normalize a)),
556+ KnownNat (I.Count (I.Normalize b)),
557+ KnownNat (I.Count (I.Normalize cols)),
558+ I.FromLists e (I.Normalize b) (I.Normalize a),
559+ I.FromLists e (I.Normalize b) (I.Normalize b),
560+ I.Normalize (Either a b) ~ Either (I.Normalize a) (I.Normalize b)
657− Matrix e cols (Either a2 rows) -> (a1 -> b) -> Matrix e cols rows
562+ => Matrix e cols (Either a b) -> (a -> b) -> Matrix e cols b
658−select m y =
563+select (M m) y = M (I.select m y)
660− in junc f identity `comp` m
662-- McCarthy's Conditional
565-- McCarthy's Conditional
664-- | McCarthy's Conditional expresses probabilistic choice.
567-- | McCarthy's Conditional expresses probabilistic choice.
666− ( cols ~ FromNat (Count cols),
569+ ( I.Normalize (I.Normalize a) ~ I.Normalize a,
667− KnownNat (Count cols),
570+ KnownNat (I.Count (I.Normalize a)),
668− FromLists e () cols,
571+ I.FromLists e () (I.Normalize a),
669− FromLists e cols (),
572+ I.FromLists e (I.Normalize a) (),
670− FromLists e cols cols,
573+ I.FromLists e (I.Normalize a) (I.Normalize a),
671 Bounded a,
574 Bounded a,
677− (a -> Bool) -> Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
580+ (a -> Bool) -> Matrix e a b -> Matrix e a b -> Matrix e a b
678−cond p f g = junc f g `comp` grd p
581+cond p (M a) (M b) = M (I.cond p a b)
681− ( q ~ FromNat (Count q),
692− (a -> Bool) -> Matrix e q (Either q q)
693−grd f = split (corr f) (corr (not . f))
697− ( q ~ FromNat (Count q),
707− => (a -> Bool) -> Matrix e q q
708−corr p = let f = fromF p :: Matrix e q ()
709− in khatri f (identity :: Matrix e q q)
711-- Pretty print
583-- Pretty print
713−prettyAux :: Show e => [[e]] -> [[e]] -> String
715−prettyAux [[e]] m = "│ " ++ fill (show e) ++ " │\n"
718− widest = maximum $ fmap length v
719− fill str = replicate (widest - length str - 2) ' ' ++ str
720−prettyAux [h] m = "│ " ++ fill (unwords $ map show h) ++ " │\n"
723− widest = maximum $ fmap length v
724− fill str = replicate (widest - length str - 2) ' ' ++ str
725−prettyAux (h : t) l = "│ " ++ fill (unwords $ map show h) ++ " │\n" ++
729− widest = maximum $ fmap length v
730− fill str = replicate (widest - length str - 2) ' ' ++ str
732-- | Matrix pretty printer
585-- | Matrix pretty printer
733−pretty :: (KnownNat (Count cols), Show e) => Matrix e cols rows -> String
586+pretty :: (KnownNat (I.Count (I.Normalize cols)), Show e) => Matrix e cols rows -> String
734−pretty m = "┌ " ++ unwords (replicate (columns m) blank) ++ " ┐\n" ++
587+pretty (M m) = I.pretty m
735− prettyAux (toLists m) (toLists m) ++
736− "└ " ++ unwords (replicate (columns m) blank) ++ " ┘"
738− v = fmap show (toList m)
739− widest = maximum $ fmap length v
740− fill str = replicate (widest - length str) ' ' ++ str
743-- | Matrix pretty printer
589-- | Matrix pretty printer
744−prettyPrint :: (KnownNat (Count cols), Show e) => Matrix e cols rows -> IO ()
590+prettyPrint :: (KnownNat (I.Count (I.Normalize cols)), Show e) => Matrix e cols rows -> IO ()
745−prettyPrint = putStrLn . pretty
591+prettyPrint (M m) = I.prettyPrint m