@@ -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,
@@ -241,7 +243,7 @@ type Trivial a = FromNat (Count a) ~ a
241243-- class.
242244instance (Num e) => Category (Matrix e) where
243245 type Object (Matrix e) a = (FL a a, Countable a)
244− id = iden
246+ id = iden
245247 (.) = comp
246248
247249instance NFData e => NFData (Matrix e cols rows) where
@@ -257,7 +259,6 @@ instance Eq e => Eq (Matrix e cols rows) where
257259 x@(Join _ _) == y@(Fork _ _) = abideJF x == y
258260
259261instance Num e => Num (Matrix e cols rows) where
260−
261262 a + b = zipWithM (+) a b
262263
263264 a - b = zipWithM (-) a b
@@ -324,7 +325,8 @@ instance (FromLists cols ()) => FromLists (Either () cols) () where
324325 fromLists [h : t] = Join (One h) (fromLists [t])
325326 fromLists _ = error "Wrong dimensions"
326327
327−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
328330 fromLists [l] =
329331 let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
330332 in Join (fromLists [take rowsA l]) (fromLists [drop rowsA l])
@@ -334,13 +336,15 @@ instance (FromLists () rows) => FromLists () (Either () rows) where
334336 fromLists ([h] : t) = Fork (One h) (fromLists t)
335337 fromLists _ = error "Wrong dimensions"
336338
337−instance {-# OVERLAPPABLE #-} (FromLists () a, FromLists () b, Countable a) => FromLists () (Either a b) where
338− fromLists l@([_] : _) =
339+instance {-# OVERLAPPABLE #-}
340+ (FromLists () a, FromLists () b, Countable a) => FromLists () (Either a b) where
341+ fromLists l@([_] : _) =
339342 let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
340343 in Fork (fromLists (take rowsA l)) (fromLists (drop rowsA l))
341344 fromLists _ = error "Wrong dimensions"
342345
343−instance (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
344348 fromLists l@(h : t) =
345349 let lh = length h
346350 rowsC = fromInteger (natVal (Proxy :: Proxy (Count c)))
@@ -367,16 +371,15 @@ matrixBuilder' f =
367371matrixBuilder ::
368372 forall e a b.
369373 ( FLN a b,
370− CountableN b,
371374 Enum a,
372375 Enum b,
373376 Bounded a,
374377 Bounded b,
375378 Eq a,
376− CountableDimsN a b
379+ Countable b
377380 ) => ((a, b) -> e) -> Matrix e (Normalize a) (Normalize b)
378381matrixBuilder f =
379− let r = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
382+ let r = fromInteger $ natVal (Proxy :: Proxy (Count b))
380383 positions = [(a, b) | a <- [minBound .. maxBound], b <- [minBound .. maxBound]]
381384 in fromLists . map (map f) . transpose . buildList r $ positions
382385 where
@@ -432,24 +435,7 @@ fromF ::
432435 ) =>
433436 (a -> b) ->
434437 Matrix e (Normalize a) (Normalize b)
435−fromF f =
436− let minA = minBound @a
437− maxA = maxBound @a
438− minB = minBound @b
439− maxB = maxBound @b
440− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
441− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
442− elementsA = take ccols [minA .. maxA]
443− elementsB = take rrows [minB .. maxB]
444− combinations = (,) <$> elementsA <*> elementsB
445− combAp = map snd . sort . map (\(a, b) -> if f a == b
446− then ((fromEnum a, fromEnum b), 1)
447− else ((fromEnum a, fromEnum b), 0)) $ combinations
448− mList = buildList combAp rrows
449− in tr $ fromLists mList
450− where
451− buildList [] _ = []
452− buildList l r = take r l : buildList (drop r l) r
438+fromF = fromF'
453439
454440-- Conversion
455441
@@ -511,7 +497,7 @@ comp (Join a b) (Fork c d) = comp a c + comp b d -- Divide-and-conquer l
511497comp (Fork a b) c = Fork (comp a c) (comp b c) -- Fork fusion law
512498comp c (Join a b) = Join (comp c a) (comp c b) -- Join fusion law
513499{-# NOINLINE comp #-}
514−{-# RULES
500+{-# RULES
515501 "comp/iden1" forall m. comp m iden = m ;
516502 "comp/iden2" forall m. comp iden m = m
517503#-}
@@ -558,24 +544,38 @@ i2 = tr p2
558544
559545-- | Obtain the number of rows.
560546--
561−-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
562−-- dimensions in constant time.
563−--
564−-- TODO: A 'rows' function that does not need the 'KnownNat' constraint in
565−-- 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''.
566550rows :: forall e cols rows. (Countable rows) => Matrix e cols rows -> Int
567551rows _ = fromInteger $ natVal (Proxy :: Proxy (Count rows))
568552
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+
569562-- | Obtain the number of columns.
570−--
571−-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
572−-- dimensions in constant time.
573563--
574−-- TODO: A 'columns' function that does not need the 'KnownNat' constraint in
575−-- 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''.
576567columns :: forall e cols rows. (Countable cols) => Matrix e cols rows -> Int
577568columns _ = fromInteger $ natVal (Proxy :: Proxy (Count cols))
578569
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+
579579-- Coproduct Bifunctor
580580
581581infixl 5 -|-
@@ -630,7 +630,7 @@ sndM = matrixBuilder' f
630630-- | Khatri Rao Matrix product also known as matrix pairing.
631631--
632632-- NOTE: That this is not a true categorical product, see for instance:
633−--
633+--
634634-- @
635635-- | fstM . kr a b == a
636636-- kr a b ==> |
@@ -666,7 +666,7 @@ infixl 4 ><
666666 FL (Normalize (m, n)) n,
667667 FL (Normalize (p, q)) p,
668668 FL (Normalize (p, q)) q
669− )
669+ )
670670 => Matrix e m p -> Matrix e n q -> Matrix e (Normalize (m, n)) (Normalize (p, q))
671671(><) a b =
672672 let fstM' = fstM @e @m @n
@@ -931,24 +931,7 @@ fromFRel' ::
931931 ) =>
932932 (a -> b) ->
933933 Relation cols rows
934−fromFRel' f =
935− let minA = minBound @a
936− maxA = maxBound @a
937− minB = minBound @b
938− maxB = maxBound @b
939− ccols = fromInteger $ natVal (Proxy :: Proxy (Count cols))
940− rrows = fromInteger $ natVal (Proxy :: Proxy (Count rows))
941− elementsA = take ccols [minA .. maxA]
942− elementsB = take rrows [minB .. maxB]
943− combinations = (,) <$> elementsA <*> elementsB
944− combAp = map snd . sort . map (\(a, b) -> if f a == b
945− then ((fromEnum a, fromEnum b), nat 1)
946− else ((fromEnum a, fromEnum b), nat 0)) $ combinations
947− mList = buildList combAp rrows
948− in tr $ fromLists mList
949− where
950− buildList [] _ = []
951− buildList l r = take r l : buildList (drop r l) r
934+fromFRel' = fromF'
952935
953936-- | Lifts functions to relations with dimensions matching @a@ and @b@
954937-- cardinality's.
@@ -956,28 +939,11 @@ fromFRel ::
956939 forall a b.
957940 ( Liftable Boolean a b,
958941 CountableDimsN a b,
959− FL (Normalize b) (Normalize a)
942+ FLN b a
960943 ) =>
961944 (a -> b) ->
962945 Relation (Normalize a) (Normalize b)
963−fromFRel f =
964− let minA = minBound @a
965− maxA = maxBound @a
966− minB = minBound @b
967− maxB = maxBound @b
968− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
969− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
970− elementsA = take ccols [minA .. maxA]
971− elementsB = take rrows [minB .. maxB]
972− combinations = (,) <$> elementsA <*> elementsB
973− combAp = map snd . sort . map (\(a, b) -> if f a == b
974− then ((fromEnum a, fromEnum b), nat 1)
975− else ((fromEnum a, fromEnum b), nat 0)) $ combinations
976− mList = buildList combAp rrows
977− in tr $ fromLists mList
978− where
979− buildList [] _ = []
980− buildList l r = take r l : buildList (drop r l) r
946+fromFRel = fromFRel'
981947
982948-- | Lifts a relation function to a Boolean Matrix
983949toRel ::
@@ -987,17 +953,17 @@ toRel ::
987953 Enum a,
988954 Enum b,
989955 Eq b,
990− CountableDimsN a b,
956+ CountableDims a b,
991957 FLN b a
992− )
958+ )
993959 => (a -> b -> Bool) -> Relation (Normalize a) (Normalize b)
994960toRel f =
995961 let minA = minBound @a
996962 maxA = maxBound @a
997963 minB = minBound @b
998964 maxB = maxBound @b
999− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
1000− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
965+ ccols = fromInteger $ natVal (Proxy :: Proxy (Count a))
966+ rrows = fromInteger $ natVal (Proxy :: Proxy (Count b))
1001967 elementsA = take ccols [minA .. maxA]
1002968 elementsB = take rrows [minB .. maxB]
1003969 combinations = (,) <$> elementsA <*> elementsB