@@ -30,7 +30,7 @@
3030-- motivation behind the library, the underlying theory, and implementation details.
3131--
3232-- This module offers many of the combinators mentioned in the work of
33−-- Macedo (2012) and Oliveira (2012).
33+-- Macedo (2012) and Oliveira (2012).
3434--
3535-- This is an Internal module and it is no supposed to be imported.
3636--
@@ -43,8 +43,8 @@ module LAoP.Matrix.Internal
4343 --
4444 -- There exists two type families that make it easier to write
4545 -- matrix dimensions: 'FromNat' and 'Count'. This approach
46− -- leads to a very straightforward implementation
47− -- of LAoP combinators.
46+ -- leads to a very straightforward implementation
47+ -- of LAoP combinators.
4848
4949 -- * Type safe matrix representation
5050 Matrix (..),
@@ -86,7 +86,9 @@ module LAoP.Matrix.Internal
8686 -- * Misc
8787 -- ** Get dimensions
8888 columns,
89+ columns',
8990 rows,
91+ rows',
9092
9193 -- ** Matrix Transposition
9294 tr,
@@ -174,6 +176,7 @@ import Data.Kind
174176import Data.List
175177import Data.Maybe
176178import Data.Proxy
179+import Data.Typeable
177180import Data.Void
178181import GHC.TypeLits
179182import Data.Type.Equality
@@ -240,7 +243,7 @@ type Trivial a = FromNat (Count a) ~ a
240243-- class.
241244instance (Num e) => Category (Matrix e) where
242245 type Object (Matrix e) a = (FL a a, Countable a)
243− id = iden
246+ id = iden
244247 (.) = comp
245248
246249instance NFData e => NFData (Matrix e cols rows) where
@@ -256,7 +259,6 @@ instance Eq e => Eq (Matrix e cols rows) where
256259 x@(Join _ _) == y@(Fork _ _) = abideJF x == y
257260
258261instance Num e => Num (Matrix e cols rows) where
259−
260262 a + b = zipWithM (+) a b
261263
262264 a - b = zipWithM (-) a b
@@ -315,31 +317,34 @@ class FromLists cols rows where
315317 -- error if the dimensions do not match.
316318 fromLists :: [[e]] -> Matrix e cols rows
317319
318−instance {-# OVERLAPPING #-} FromLists () () where
320+instance FromLists () () where
319321 fromLists [[e]] = One e
320322 fromLists _ = error "Wrong dimensions"
321323
322−instance {-# OVERLAPPING #-} (FromLists cols ()) => FromLists (Either () cols) () where
324+instance (FromLists cols ()) => FromLists (Either () cols) () where
323325 fromLists [h : t] = Join (One h) (fromLists [t])
324326 fromLists _ = error "Wrong dimensions"
325327
326−instance {-# OVERLAPPABLE #-} (FromLists a (), FromLists b (), Countable a) => FromLists (Either a b) () where
328+instance {-# OVERLAPPABLE #-}
329+ (FromLists a (), FromLists b (), Countable a) => FromLists (Either a b) () where
327330 fromLists [l] =
328331 let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
329332 in Join (fromLists [take rowsA l]) (fromLists [drop rowsA l])
330333 fromLists _ = error "Wrong dimensions"
331334
332−instance {-# OVERLAPPING #-} (FromLists () rows) => FromLists () (Either () rows) where
335+instance (FromLists () rows) => FromLists () (Either () rows) where
333336 fromLists ([h] : t) = Fork (One h) (fromLists t)
334337 fromLists _ = error "Wrong dimensions"
335338
336−instance {-# OVERLAPPABLE #-} (FromLists () a, FromLists () b, Countable a) => FromLists () (Either a b) where
337− fromLists l@([_] : _) =
339+instance {-# OVERLAPPABLE #-}
340+ (FromLists () a, FromLists () b, Countable a) => FromLists () (Either a b) where
341+ fromLists l@([_] : _) =
338342 let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
339343 in Fork (fromLists (take rowsA l)) (fromLists (drop rowsA l))
340344 fromLists _ = error "Wrong dimensions"
341345
342−instance {-# OVERLAPPABLE #-} (FromLists (Either a b) c, FromLists (Either a b) d, Countable c) => FromLists (Either a b) (Either c d) where
346+instance (FromLists (Either a b) c, FromLists (Either a b) d, Countable c)
347+ => FromLists (Either a b) (Either c d) where
343348 fromLists l@(h : t) =
344349 let lh = length h
345350 rowsC = fromInteger (natVal (Proxy :: Proxy (Count c)))
@@ -366,16 +371,15 @@ matrixBuilder' f =
366371matrixBuilder ::
367372 forall e a b.
368373 ( FLN a b,
369− CountableN b,
370374 Enum a,
371375 Enum b,
372376 Bounded a,
373377 Bounded b,
374378 Eq a,
375− CountableDimsN a b
379+ Countable b
376380 ) => ((a, b) -> e) -> Matrix e (Normalize a) (Normalize b)
377381matrixBuilder f =
378− let r = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
382+ let r = fromInteger $ natVal (Proxy :: Proxy (Count b))
379383 positions = [(a, b) | a <- [minBound .. maxBound], b <- [minBound .. maxBound]]
380384 in fromLists . map (map f) . transpose . buildList r $ positions
381385 where
@@ -431,24 +435,7 @@ fromF ::
431435 ) =>
432436 (a -> b) ->
433437 Matrix e (Normalize a) (Normalize b)
434−fromF f =
435− let minA = minBound @a
436− maxA = maxBound @a
437− minB = minBound @b
438− maxB = maxBound @b
439− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
440− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
441− elementsA = take ccols [minA .. maxA]
442− elementsB = take rrows [minB .. maxB]
443− combinations = (,) <$> elementsA <*> elementsB
444− combAp = map snd . sort . map (\(a, b) -> if f a == b
445− then ((fromEnum a, fromEnum b), 1)
446− else ((fromEnum a, fromEnum b), 0)) $ combinations
447− mList = buildList combAp rrows
448− in tr $ fromLists mList
449− where
450− buildList [] _ = []
451− buildList l r = take r l : buildList (drop r l) r
438+fromF = fromF'
452439
453440-- Conversion
454441
@@ -510,7 +497,7 @@ comp (Join a b) (Fork c d) = comp a c + comp b d -- Divide-and-conquer l
510497comp (Fork a b) c = Fork (comp a c) (comp b c) -- Fork fusion law
511498comp c (Join a b) = Join (comp c a) (comp c b) -- Join fusion law
512499{-# NOINLINE comp #-}
513−{-# RULES
500+{-# RULES
514501 "comp/iden1" forall m. comp m iden = m ;
515502 "comp/iden2" forall m. comp iden m = m
516503#-}
@@ -557,24 +544,38 @@ i2 = tr p2
557544
558545-- | Obtain the number of rows.
559546--
560−-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
561−-- dimensions in constant time.
562−--
563−-- TODO: A 'rows' function that does not need the 'KnownNat' constraint in
564−-- exchange for performance.
547+-- NOTE: The 'KnownNat' constraint is needed in order to obtain the
548+-- dimensions in constant time. For a version that doesn't require the
549+-- constraint see 'rows''.
565550rows :: forall e cols rows. (Countable rows) => Matrix e cols rows -> Int
566551rows _ = fromInteger $ natVal (Proxy :: Proxy (Count rows))
567552
553+-- | Obtain the number of rows in an inefficient manner, but without any
554+-- constraints.
555+--
556+-- For a more efficient version see 'rows'.
557+rows' :: Matrix e cols rows -> Int
558+rows' (One _) = 1
559+rows' (Join lhs _) = rows' lhs
560+rows' (Fork top bottom) = rows' top + rows' bottom
561+
568562-- | Obtain the number of columns.
569−--
570−-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
571−-- dimensions in constant time.
572563--
573−-- TODO: A 'columns' function that does not need the 'KnownNat' constraint in
574−-- exchange for performance.
564+-- NOTE: The 'KnownNat' constraint is needed in order to obtain the
565+-- dimensions in constant time. For a version that doesn't require the
566+-- constraint see 'columns''.
575567columns :: forall e cols rows. (Countable cols) => Matrix e cols rows -> Int
576568columns _ = fromInteger $ natVal (Proxy :: Proxy (Count cols))
577569
570+-- | Obtain the number of columns in an inefficient manner, but without any
571+-- constraints.
572+--
573+-- For a more efficient version see 'columns'.
574+columns' :: Matrix e cols rows -> Int
575+columns' (One _) = 1
576+columns' (Join lhs rhs) = columns' lhs + columns' rhs
577+columns' (Fork top _) = columns' top
578+
578579-- Coproduct Bifunctor
579580
580581infixl 5 -|-
@@ -629,7 +630,7 @@ sndM = matrixBuilder' f
629630-- | Khatri Rao Matrix product also known as matrix pairing.
630631--
631632-- NOTE: That this is not a true categorical product, see for instance:
632−--
633+--
633634-- @
634635-- | fstM . kr a b == a
635636-- kr a b ==> |
@@ -665,7 +666,7 @@ infixl 4 ><
665666 FL (Normalize (m, n)) n,
666667 FL (Normalize (p, q)) p,
667668 FL (Normalize (p, q)) q
668− )
669+ )
669670 => Matrix e m p -> Matrix e n q -> Matrix e (Normalize (m, n)) (Normalize (p, q))
670671(><) a b =
671672 let fstM' = fstM @e @m @n
@@ -930,24 +931,7 @@ fromFRel' ::
930931 ) =>
931932 (a -> b) ->
932933 Relation cols rows
933−fromFRel' f =
934− let minA = minBound @a
935− maxA = maxBound @a
936− minB = minBound @b
937− maxB = maxBound @b
938− ccols = fromInteger $ natVal (Proxy :: Proxy (Count cols))
939− rrows = fromInteger $ natVal (Proxy :: Proxy (Count rows))
940− elementsA = take ccols [minA .. maxA]
941− elementsB = take rrows [minB .. maxB]
942− combinations = (,) <$> elementsA <*> elementsB
943− combAp = map snd . sort . map (\(a, b) -> if f a == b
944− then ((fromEnum a, fromEnum b), nat 1)
945− else ((fromEnum a, fromEnum b), nat 0)) $ combinations
946− mList = buildList combAp rrows
947− in tr $ fromLists mList
948− where
949− buildList [] _ = []
950− buildList l r = take r l : buildList (drop r l) r
934+fromFRel' = fromF'
951935
952936-- | Lifts functions to relations with dimensions matching @a@ and @b@
953937-- cardinality's.
@@ -955,28 +939,11 @@ fromFRel ::
955939 forall a b.
956940 ( Liftable Boolean a b,
957941 CountableDimsN a b,
958− FL (Normalize b) (Normalize a)
942+ FLN b a
959943 ) =>
960944 (a -> b) ->
961945 Relation (Normalize a) (Normalize b)
962−fromFRel f =
963− let minA = minBound @a
964− maxA = maxBound @a
965− minB = minBound @b
966− maxB = maxBound @b
967− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
968− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
969− elementsA = take ccols [minA .. maxA]
970− elementsB = take rrows [minB .. maxB]
971− combinations = (,) <$> elementsA <*> elementsB
972− combAp = map snd . sort . map (\(a, b) -> if f a == b
973− then ((fromEnum a, fromEnum b), nat 1)
974− else ((fromEnum a, fromEnum b), nat 0)) $ combinations
975− mList = buildList combAp rrows
976− in tr $ fromLists mList
977− where
978− buildList [] _ = []
979− buildList l r = take r l : buildList (drop r l) r
946+fromFRel = fromFRel'
980947
981948-- | Lifts a relation function to a Boolean Matrix
982949toRel ::
@@ -986,17 +953,17 @@ toRel ::
986953 Enum a,
987954 Enum b,
988955 Eq b,
989− CountableDimsN a b,
956+ CountableDims a b,
990957 FLN b a
991− )
958+ )
992959 => (a -> b -> Bool) -> Relation (Normalize a) (Normalize b)
993960toRel f =
994961 let minA = minBound @a
995962 maxA = maxBound @a
996963 minB = minBound @b
997964 maxB = maxBound @b
998− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
999− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
965+ ccols = fromInteger $ natVal (Proxy :: Proxy (Count a))
966+ rrows = fromInteger $ natVal (Proxy :: Proxy (Count b))
1000967 elementsA = take ccols [minA .. maxA]
1001968 elementsB = take rrows [minB .. maxB]
1002969 combinations = (,) <$> elementsA <*> elementsB