@@ -30,7 +30,7 @@
30-- motivation behind the library, the underlying theory, and implementation details.
30-- motivation behind the library, the underlying theory, and implementation details.
32-- This module offers many of the combinators mentioned in the work of
32-- This module offers many of the combinators mentioned in the work of
33−-- Macedo (2012) and Oliveira (2012).
33+-- Macedo (2012) and Oliveira (2012).
35-- This is an Internal module and it is no supposed to be imported.
35-- This is an Internal module and it is no supposed to be imported.
@@ -43,17 +43,26 @@ module LAoP.Matrix.Internal
44 -- There exists two type families that make it easier to write
44 -- There exists two type families that make it easier to write
45 -- matrix dimensions: 'FromNat' and 'Count'. This approach
45 -- matrix dimensions: 'FromNat' and 'Count'. This approach
46− -- leads to a very straightforward implementation
46+ -- leads to a very straightforward implementation
47− -- of LAoP combinators.
47+ -- of LAoP combinators.
49 -- * Type safe matrix representation
49 -- * Type safe matrix representation
50 Matrix (..),
50 Matrix (..),
52+ -- * Constraint type aliases
52 -- * Primitives
62 -- * Primitives
58 -- * Auxiliary type families
67 -- * Auxiliary type families
@@ -66,6 +75,7 @@ module LAoP.Matrix.Internal
68 matrixBuilder,
77 matrixBuilder,
@@ -76,11 +86,17 @@ module LAoP.Matrix.Internal
77 -- ** Get dimensions
87 -- ** Get dimensions
81 -- ** Matrix Transposition
93 -- ** Matrix Transposition
96+ -- ** Scalar multiplication/division of matrices
84 -- ** Selective operator
100 -- ** Selective operator
@@ -89,19 +105,19 @@ module LAoP.Matrix.Internal
91 -- ** Matrix "abiding"
107 -- ** Matrix "abiding"
92− abideJS,
108+ abideJF,
93− abideSJ,
109+ abideFJ,
95 -- ** Zip matrices
111 -- ** Zip matrices
96 zipWithM,
112 zipWithM,
98 -- * Biproduct approach
114 -- * Biproduct approach
99− -- ** Split
115+ -- ** Fork
101 -- *** Projections
117 -- *** Projections
104− -- ** Junc
120+ -- ** Join
106 -- *** Injections
122 -- *** Injections
@@ -114,12 +130,13 @@ module LAoP.Matrix.Internal
115 -- | Note that given the restrictions imposed it is not possible to
131 -- | Note that given the restrictions imposed it is not possible to
116 -- implement the standard type classes present in standard Haskell.
132 -- implement the standard type classes present in standard Haskell.
117 -- *** Matrix pairing projections
134 -- *** Matrix pairing projections
121 -- *** Matrix pairing
138 -- *** Matrix pairing
124 -- * Matrix composition and lifting
141 -- * Matrix composition and lifting
@@ -127,10 +144,10 @@ module LAoP.Matrix.Internal
128 -- | Note that given the restrictions imposed it is not possible to
145 -- | Note that given the restrictions imposed it is not possible to
129 -- implement the standard type classes present in standard Haskell.
146 -- implement the standard type classes present in standard Haskell.
135 -- * Matrix printing
152 -- * Matrix printing
@@ -159,20 +176,20 @@ import Data.Kind
159import Data.List
176import Data.List
160import Data.Maybe
177import Data.Maybe
161import Data.Proxy
178import Data.Proxy
162import Data.Void
180import Data.Void
163import GHC.TypeLits
181import GHC.TypeLits
164import Data.Type.Equality
182import Data.Type.Equality
165import GHC.Generics
183import GHC.Generics
166import Control.DeepSeq
184import Control.DeepSeq
167−import Control.Category
185+import Prelude hiding (id, (.))
168−import Prelude hiding ((.))
186+import qualified Prelude (id, (.))
170-- | LAoP (Linear Algebra of Programming) Inductive Matrix definition.
188-- | LAoP (Linear Algebra of Programming) Inductive Matrix definition.
171data Matrix e cols rows where
189data Matrix e cols rows where
172− Empty :: Matrix e Void Void
173 One :: e -> Matrix e () ()
190 One :: e -> Matrix e () ()
174− Junc :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
191+ Join :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
175− Split :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
192+ Fork :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
177deriving instance (Show e) => Show (Matrix e cols rows)
194deriving instance (Show e) => Show (Matrix e cols rows)
@@ -199,7 +216,6 @@ type family Count (d :: Type) :: Nat where
200-- Thanks to Li-Yao Xia this type family is super fast.
217-- Thanks to Li-Yao Xia this type family is super fast.
201type family FromNat (n :: Nat) :: Type where
218type family FromNat (n :: Nat) :: Type where
203 FromNat 1 = ()
219 FromNat 1 = ()
204 FromNat n = FromNat' (Mod n 2 == 0) (FromNat (Div n 2))
220 FromNat n = FromNat' (Mod n 2 == 0) (FromNat (Div n 2))
@@ -216,90 +232,79 @@ type family Normalize (d :: Type) :: Type where
216-- | Constraint type synonyms to keep the type signatures less convoluted
232-- | Constraint type synonyms to keep the type signatures less convoluted
217type Countable a = KnownNat (Count a)
233type Countable a = KnownNat (Count a)
218type CountableN a = KnownNat (Count (Normalize a))
234type CountableN a = KnownNat (Count (Normalize a))
219−type CountableDimensions a b = (Countable a, Countable b)
235+type CountableDims a b = (Countable a, Countable b)
220−type CountableDimensionsN a b = (CountableN a, CountableN b)
236+type CountableDimsN a b = (CountableN a, CountableN b)
237+type FL a b = FromLists a b
221−type FromListsN e a b = FromLists e (Normalize a) (Normalize b)
238+type FLN a b = FromLists (Normalize a) (Normalize b)
222type Liftable e a b = (Bounded a, Bounded b, Enum a, Enum b, Eq b, Num e, Ord e)
239type Liftable e a b = (Bounded a, Bounded b, Enum a, Enum b, Eq b, Num e, Ord e)
223type Trivial a = FromNat (Count a) ~ a
240type Trivial a = FromNat (Count a) ~ a
225−-- | It isn't possible to implement the 'id' function so it's
242+-- | It is possible to implement a constrained version of the category type
226−-- implementation is 'undefined'. However 'comp' can be and this partial
243+-- class.
227−-- class implementation exists just to make the code more readable.
229−-- Please use 'identity' instead.
230instance (Num e) => Category (Matrix e) where
244instance (Num e) => Category (Matrix e) where
231− id = undefined
245+ type Object (Matrix e) a = (FL a a, Countable a)
232− (.) = comp
247+ (.) = comp
234instance NFData e => NFData (Matrix e cols rows) where
249instance NFData e => NFData (Matrix e cols rows) where
236− rnf (One e) = rnf e
250+ rnf (One e) = rnf e
237− rnf (Junc a b) = rnf a `seq` rnf b
251+ rnf (Join a b) = rnf a `seq` rnf b
238− rnf (Split a b) = rnf a `seq` rnf b
252+ rnf (Fork a b) = rnf a `seq` rnf b
240instance Eq e => Eq (Matrix e cols rows) where
254instance Eq e => Eq (Matrix e cols rows) where
241− Empty == Empty = True
242− (One a) == (One b) = a == b
255+ (One a) == (One b) = a == b
243− (Junc a b) == (Junc c d) = a == c && b == d
256+ (Join a b) == (Join c d) = a == c && b == d
244− (Split a b) == (Split c d) = a == c && b == d
257+ (Fork a b) == (Fork c d) = a == c && b == d
245− x@(Split _ _) == y@(Junc _ _) = x == abideJS y
258+ x@(Fork _ _) == y@(Join _ _) = x == abideJF y
246− x@(Junc _ _) == y@(Split _ _) = abideJS x == y
259+ x@(Join _ _) == y@(Fork _ _) = abideJF x == y
248instance Num e => Num (Matrix e cols rows) where
261instance Num e => Num (Matrix e cols rows) where
250 a + b = zipWithM (+) a b
262 a + b = zipWithM (+) a b
252 a - b = zipWithM (-) a b
264 a - b = zipWithM (-) a b
254 a * b = zipWithM (*) a b
266 a * b = zipWithM (*) a b
257− abs (One a) = One (abs a)
268+ abs (One a) = One (abs a)
258− abs (Junc a b) = Junc (abs a) (abs b)
269+ abs (Join a b) = Join (abs a) (abs b)
259− abs (Split a b) = Split (abs a) (abs b)
270+ abs (Fork a b) = Fork (abs a) (abs b)
261− signum Empty = Empty
262− signum (One a) = One (signum a)
272+ signum (One a) = One (signum a)
263− signum (Junc a b) = Junc (signum a) (signum b)
273+ signum (Join a b) = Join (signum a) (signum b)
264− signum (Split a b) = Split (signum a) (signum b)
274+ signum (Fork a b) = Fork (signum a) (signum b)
266instance Ord e => Ord (Matrix e cols rows) where
276instance Ord e => Ord (Matrix e cols rows) where
267− Empty <= Empty = True
268− (One a) <= (One b) = a <= b
277+ (One a) <= (One b) = a <= b
269− (Junc a b) <= (Junc c d) = (a <= c) && (b <= d)
278+ (Join a b) <= (Join c d) = (a <= c) && (b <= d)
270− (Split a b) <= (Split c d) = (a <= c) && (b <= d)
279+ (Fork a b) <= (Fork c d) = (a <= c) && (b <= d)
271− x@(Split _ _) <= y@(Junc _ _) = x <= abideJS y
280+ x@(Fork _ _) <= y@(Join _ _) = x <= abideJF y
272− x@(Junc _ _) <= y@(Split _ _) = abideJS x <= y
281+ x@(Join _ _) <= y@(Fork _ _) = abideJF x <= y
274-- Primitives
283-- Primitives
276−-- | Empty matrix constructor
277−empty :: Matrix e Void Void
280-- | Unit matrix constructor
285-- | Unit matrix constructor
281one :: e -> Matrix e () ()
286one :: e -> Matrix e () ()
284−-- | Matrix 'Junc' constructor
289+-- | Matrix 'Join' constructor
285−junc :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
290+join :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
286−junc = Junc
291+join = Join
288infixl 3 |||
293infixl 3 |||
290−-- | Matrix 'Junc' constructor
295+-- | Matrix 'Join' constructor
291(|||) :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
296(|||) :: Matrix e a rows -> Matrix e b rows -> Matrix e (Either a b) rows
292−(|||) = Junc
297+(|||) = Join
294−-- | Matrix 'Split' constructor
299+-- | Matrix 'Fork' constructor
295−split :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
300+fork :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
296−split = Split
301+fork = Fork
298infixl 2 ===
303infixl 2 ===
300−-- | Matrix 'Split' constructor
305+-- | Matrix 'Fork' constructor
301(===) :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
306(===) :: Matrix e cols a -> Matrix e cols b -> Matrix e cols (Either a b)
302−(===) = Split
307+(===) = Fork
304-- Construction
309-- Construction
@@ -307,84 +312,101 @@ infixl 2 ===
308-- Given that it is not possible to branch on types at the term level type
313-- Given that it is not possible to branch on types at the term level type
309-- classes are needed very much like an inductive definition but on types.
314-- classes are needed very much like an inductive definition but on types.
310−class FromLists e cols rows where
315+class FromLists cols rows where
311 -- | Build a matrix out of a list of list of elements. Throws a runtime
316 -- | Build a matrix out of a list of list of elements. Throws a runtime
312 -- error if the dimensions do not match.
317 -- error if the dimensions do not match.
313 fromLists :: [[e]] -> Matrix e cols rows
318 fromLists :: [[e]] -> Matrix e cols rows
315−instance FromLists e Void Void where
320+instance FromLists () () where
316− fromLists [] = Empty
317− fromLists _ = error "Wrong dimensions"
319−instance {-# OVERLAPPING #-} FromLists e () () where
320 fromLists [[e]] = One e
321 fromLists [[e]] = One e
321 fromLists _ = error "Wrong dimensions"
322 fromLists _ = error "Wrong dimensions"
323−instance {-# OVERLAPPING #-} (FromLists e cols ()) => FromLists e (Either () cols) () where
324+instance (FromLists cols ()) => FromLists (Either () cols) () where
324− fromLists [h : t] = Junc (One h) (fromLists [t])
325+ fromLists [h : t] = Join (One h) (fromLists [t])
325 fromLists _ = error "Wrong dimensions"
326 fromLists _ = error "Wrong dimensions"
328+instance {-# OVERLAPPABLE #-}
327−instance {-# OVERLAPPABLE #-} (FromLists e a (), FromLists e b (), Countable a) => FromLists e (Either a b) () where
329+ (FromLists a (), FromLists b (), Countable a) => FromLists (Either a b) () where
328− fromLists [l] =
330+ fromLists [l] =
329 let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
331 let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
330− in Junc (fromLists [take rowsA l]) (fromLists [drop rowsA l])
332+ in Join (fromLists [take rowsA l]) (fromLists [drop rowsA l])
331 fromLists _ = error "Wrong dimensions"
333 fromLists _ = error "Wrong dimensions"
333−instance {-# OVERLAPPING #-} (FromLists e () rows) => FromLists e () (Either () rows) where
335+instance (FromLists () rows) => FromLists () (Either () rows) where
334− fromLists ([h] : t) = Split (One h) (fromLists t)
336+ fromLists ([h] : t) = Fork (One h) (fromLists t)
335 fromLists _ = error "Wrong dimensions"
337 fromLists _ = error "Wrong dimensions"
339+instance {-# OVERLAPPABLE #-}
337−instance {-# OVERLAPPABLE #-} (FromLists e () a, FromLists e () b, Countable a) => FromLists e () (Either a b) where
340+ (FromLists () a, FromLists () b, Countable a) => FromLists () (Either a b) where
338− fromLists l@([_] : _) =
341+ fromLists l@([_] : _) =
339 let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
342 let rowsA = fromInteger (natVal (Proxy :: Proxy (Count a)))
340− in Split (fromLists (take rowsA l)) (fromLists (drop rowsA l))
343+ in Fork (fromLists (take rowsA l)) (fromLists (drop rowsA l))
341 fromLists _ = error "Wrong dimensions"
344 fromLists _ = error "Wrong dimensions"
343−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
346+instance (FromLists (Either a b) c, FromLists (Either a b) d, Countable c)
347+ => FromLists (Either a b) (Either c d) where
344 fromLists l@(h : t) =
348 fromLists l@(h : t) =
345 let lh = length h
349 let lh = length h
346 rowsC = fromInteger (natVal (Proxy :: Proxy (Count c)))
350 rowsC = fromInteger (natVal (Proxy :: Proxy (Count c)))
347− condition = all (== lh) (map length t)
351+ condition = all ((== lh) . length) t
348 in if lh > 0 && condition
352 in if lh > 0 && condition
349− then Split (fromLists (take rowsC l)) (fromLists (drop rowsC l))
353+ then Fork (fromLists (take rowsC l)) (fromLists (drop rowsC l))
350 else error "Not all rows have the same length"
354 else error "Not all rows have the same length"
352-- | Matrix builder function. Constructs a matrix provided with
356-- | Matrix builder function. Constructs a matrix provided with
353−-- a construction function.
357+-- a construction function that operates with indices.
354−matrixBuilder ::
358+matrixBuilder' ::
355 forall e cols rows.
359 forall e cols rows.
356− ( FromLists e cols rows,
360+ ( FL cols rows,
357− CountableDimensions cols rows
361+ CountableDims cols rows
359− ((Int, Int) -> e) ->
360− Matrix e cols rows
362+ ) => ((Int, Int) -> e) -> Matrix e cols rows
361−matrixBuilder f =
363+matrixBuilder' f =
362 let c = fromInteger $ natVal (Proxy :: Proxy (Count cols))
364 let c = fromInteger $ natVal (Proxy :: Proxy (Count cols))
363 r = fromInteger $ natVal (Proxy :: Proxy (Count rows))
365 r = fromInteger $ natVal (Proxy :: Proxy (Count rows))
364 positions = [(a, b) | a <- [0 .. (r - 1)], b <- [0 .. (c - 1)]]
366 positions = [(a, b) | a <- [0 .. (r - 1)], b <- [0 .. (c - 1)]]
365 in fromLists . map (map f) . groupBy (\(x, _) (w, _) -> x == w) $ positions
367 in fromLists . map (map f) . groupBy (\(x, _) (w, _) -> x == w) $ positions
369+-- | Matrix builder function. Constructs a matrix provided with
370+-- a construction function that operates with arbitrary types.
380+ ) => ((a, b) -> e) -> Matrix e (Normalize a) (Normalize b)
382+ let r = fromInteger $ natVal (Proxy :: Proxy (Count b))
383+ positions = [(a, b) | a <- [minBound .. maxBound], b <- [minBound .. maxBound]]
384+ in fromLists . map (map f) . transpose . buildList r $ positions
387+ buildList r l = take r l : buildList r (drop r l)
367-- | Constructs a column vector matrix
389-- | Constructs a column vector matrix
368−col :: (FromLists e () rows) => [e] -> Matrix e () rows
390+col :: (FL () rows) => [e] -> Matrix e () rows
369col = fromLists . map (: [])
391col = fromLists . map (: [])
371-- | Constructs a row vector matrix
393-- | Constructs a row vector matrix
372−row :: (FromLists e cols ()) => [e] -> Matrix e cols ()
394+row :: (FL cols ()) => [e] -> Matrix e cols ()
373row = fromLists . (: [])
395row = fromLists . (: [])
375-- | Lifts functions to matrices with arbitrary dimensions.
397-- | Lifts functions to matrices with arbitrary dimensions.
377-- NOTE: Be careful to not ask for a matrix bigger than the cardinality of
399-- NOTE: Be careful to not ask for a matrix bigger than the cardinality of
378-- types @a@ or @b@ allows.
400-- types @a@ or @b@ allows.
379−fromF ::
401+fromF' ::
380 forall a b cols rows e.
402 forall a b cols rows e.
381 ( Liftable e a b,
403 ( Liftable e a b,
382− CountableDimensions cols rows,
404+ CountableDims cols rows,
383− FromLists e rows cols
405+ FL rows cols
385 (a -> b) ->
407 (a -> b) ->
386 Matrix e cols rows
408 Matrix e cols rows
387−fromF f =
409+fromF' f =
388 let minA = minBound @a
410 let minA = minBound @a
389 maxA = maxBound @a
411 maxA = maxBound @a
390 minB = minBound @b
412 minB = minBound @b
@@ -394,8 +416,8 @@ fromF f =
394 elementsA = take ccols [minA .. maxA]
416 elementsA = take ccols [minA .. maxA]
395 elementsB = take rrows [minB .. maxB]
417 elementsB = take rrows [minB .. maxB]
396 combinations = (,) <$> elementsA <*> elementsB
418 combinations = (,) <$> elementsA <*> elementsB
397− combAp = map snd . sort . map (\(a, b) -> if f a == b
419+ combAp = map snd . sort . map (\(a, b) -> if f a == b
398− then ((fromEnum a, fromEnum b), 1)
420+ then ((fromEnum a, fromEnum b), 1)
399 else ((fromEnum a, fromEnum b), 0)) $ combinations
421 else ((fromEnum a, fromEnum b), 0)) $ combinations
400 mList = buildList combAp rrows
422 mList = buildList combAp rrows
401 in tr $ fromLists mList
423 in tr $ fromLists mList
@@ -405,41 +427,23 @@ fromF f =
406-- | Lifts functions to matrices with dimensions matching @a@ and @b@
428-- | Lifts functions to matrices with dimensions matching @a@ and @b@
407-- cardinality's.
429-- cardinality's.
408−fromF' ::
430+fromF ::
409 forall a b e.
431 forall a b e.
410 ( Liftable e a b,
432 ( Liftable e a b,
411− CountableDimensionsN a b,
433+ CountableDimsN a b,
412− FromListsN e b a
434+ FLN b a
414 (a -> b) ->
436 (a -> b) ->
415 Matrix e (Normalize a) (Normalize b)
437 Matrix e (Normalize a) (Normalize b)
416−fromF' f =
438+fromF = fromF'
417− let minA = minBound @a
421− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
422− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
423− elementsA = take ccols [minA .. maxA]
424− elementsB = take rrows [minB .. maxB]
425− combinations = (,) <$> elementsA <*> elementsB
426− combAp = map snd . sort . map (\(a, b) -> if f a == b
427− then ((fromEnum a, fromEnum b), 1)
428− else ((fromEnum a, fromEnum b), 0)) $ combinations
429− mList = buildList combAp rrows
430− in tr $ fromLists mList
433− buildList l r = take r l : buildList (drop r l) r
435-- Conversion
440-- Conversion
437-- | Converts a matrix to a list of lists of elements.
442-- | Converts a matrix to a list of lists of elements.
438toLists :: Matrix e cols rows -> [[e]]
443toLists :: Matrix e cols rows -> [[e]]
440toLists (One e) = [[e]]
444toLists (One e) = [[e]]
441−toLists (Split l r) = toLists l ++ toLists r
445+toLists (Fork l r) = toLists l ++ toLists r
442−toLists (Junc l r) = zipWith (++) (toLists l) (toLists r)
446+toLists (Join l r) = zipWith (++) (toLists l) (toLists r)
444-- | Converts a matrix to a list of elements.
448-- | Converts a matrix to a list of elements.
445toList :: Matrix e cols rows -> [e]
449toList :: Matrix e cols rows -> [e]
@@ -448,38 +452,38 @@ toList = concat . toLists
448-- Zeros Matrix
452-- Zeros Matrix
450-- | The zero matrix. A matrix wholly filled with zeros.
454-- | The zero matrix. A matrix wholly filled with zeros.
451−zeros :: (Num e, FromLists e cols rows, CountableDimensions cols rows) => Matrix e cols rows
455+zeros :: (Num e, FL cols rows, CountableDims cols rows) => Matrix e cols rows
452−zeros = matrixBuilder (const 0)
456+zeros = matrixBuilder' (const 0)
454-- Ones Matrix
458-- Ones Matrix
456-- | The ones matrix. A matrix wholly filled with ones.
460-- | The ones matrix. A matrix wholly filled with ones.
458-- Also known as T (Top) matrix.
462-- Also known as T (Top) matrix.
459−ones :: (Num e, FromLists e cols rows, CountableDimensions cols rows) => Matrix e cols rows
463+ones :: (Num e, FL cols rows, CountableDims cols rows) => Matrix e cols rows
460−ones = matrixBuilder (const 1)
464+ones = matrixBuilder' (const 1)
462-- Const Matrix
466-- Const Matrix
464-- | The constant matrix constructor. A matrix wholly filled with a given
468-- | The constant matrix constructor. A matrix wholly filled with a given
466−constant :: (Num e, FromLists e cols rows, CountableDimensions cols rows) => e -> Matrix e cols rows
470+constant :: (Num e, FL cols rows, CountableDims cols rows) => e -> Matrix e cols rows
467−constant e = matrixBuilder (const e)
471+constant e = matrixBuilder' (const e)
469-- Bang Matrix
473-- Bang Matrix
471-- | The T (Top) row vector matrix.
475-- | The T (Top) row vector matrix.
472−bang :: forall e cols. (Num e, Enum e, FromLists e cols (), Countable cols) => Matrix e cols ()
476+bang :: forall e cols. (Num e, Enum e, FL cols (), Countable cols) => Matrix e cols ()
474 let c = fromInteger $ natVal (Proxy :: Proxy (Count cols))
478 let c = fromInteger $ natVal (Proxy :: Proxy (Count cols))
475 in fromLists [take c [1, 1 ..]]
479 in fromLists [take c [1, 1 ..]]
477−-- Identity Matrix
481+-- iden Matrix
479−-- | Identity matrix.
483+-- | iden matrix.
480−identity :: (Num e, FromLists e cols cols, Countable cols) => Matrix e cols cols
484+iden :: forall e cols . (Num e, FL cols cols, Countable cols) => Matrix e cols cols
481−identity = matrixBuilder (bool 0 1 . uncurry (==))
485+iden = matrixBuilder' (bool 0 1 . uncurry (==))
482−{-# NOINLINE identity #-}
486+{-# NOINLINE iden #-}
484-- Matrix composition (MMM)
488-- Matrix composition (MMM)
@@ -488,65 +492,90 @@ identity = matrixBuilder (bool 0 1 . uncurry (==))
488-- This definition takes advantage of divide-and-conquer and fusion laws
492-- This definition takes advantage of divide-and-conquer and fusion laws
489-- from LAoP.
493-- from LAoP.
490comp :: (Num e) => Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
494comp :: (Num e) => Matrix e cr rows -> Matrix e cols cr -> Matrix e cols rows
491−comp Empty Empty = Empty
492−comp (One a) (One b) = One (a * b)
495+comp (One a) (One b) = One (a * b)
493−comp (Junc a b) (Split c d) = comp a c + comp b d -- Divide-and-conquer law
496+comp (Join a b) (Fork c d) = comp a c + comp b d -- Divide-and-conquer law
494−comp (Split a b) c = Split (comp a c) (comp b c) -- Split fusion law
497+comp (Fork a b) c = Fork (comp a c) (comp b c) -- Fork fusion law
495−comp c (Junc a b) = Junc (comp c a) (comp c b) -- Junc fusion law
498+comp c (Join a b) = Join (comp c a) (comp c b) -- Join fusion law
496{-# NOINLINE comp #-}
499{-# NOINLINE comp #-}
497−{-# RULES
500+{-# RULES
498− "comp/identity1" forall m. comp m identity = m ;
501+ "comp/iden1" forall m. comp m iden = m ;
499− "comp/identity2" forall m. comp identity m = m
502+ "comp/iden2" forall m. comp iden m = m
505+-- Scalar multiplication of matrices
508+-- | Scalar multiplication of matrices.
509+(.|) :: Num e => e -> Matrix e cols rows -> Matrix e cols rows
510+(.|) e (One a) = One (e * a)
511+(.|) e (Join a b) = Join (e .| a) (e .| b)
512+(.|) e (Fork a b) = Fork (e .| a) (e .| b)
514+-- Scalar division of matrices
517+-- | Scalar multiplication of matrices.
518+(./) :: Fractional e => Matrix e cols rows -> e -> Matrix e cols rows
519+(./) (One a) e = One (a / e)
520+(./) (Join a b) e = Join (a ./ e) (b ./ e)
521+(./) (Fork a b) e = Fork (a ./ e) (b ./ e)
502-- Projections
523-- Projections
504-- | Biproduct first component projection
525-- | Biproduct first component projection
505−p1 :: forall e m n. (Num e, CountableDimensions n m, FromLists e n m, FromLists e m m) => Matrix e (Either m n) m
526+p1 :: (Num e, CountableDims n m, FL n m, FL m m) => Matrix e (Either m n) m
506−p1 =
527+p1 = join id zeros
507− let iden = identity :: Matrix e m m
508− zero = zeros :: Matrix e n m
511-- | Biproduct second component projection
529-- | Biproduct second component projection
512−p2 :: forall e m n. (Num e, CountableDimensions n m, FromLists e m n, FromLists e n n) => Matrix e (Either m n) n
530+p2 :: (Num e, CountableDims n m, FL m n, FL n n) => Matrix e (Either m n) n
513−p2 =
531+p2 = join zeros id
514− let iden = identity :: Matrix e n n
515− zero = zeros :: Matrix e m n
518-- Injections
533-- Injections
520-- | Biproduct first component injection
535-- | Biproduct first component injection
521−i1 :: (Num e, CountableDimensions n m, FromLists e n m, FromLists e m m) => Matrix e m (Either m n)
536+i1 :: (Num e, CountableDims n m, FL n m, FL m m) => Matrix e m (Either m n)
522i1 = tr p1
537i1 = tr p1
524-- | Biproduct second component injection
539-- | Biproduct second component injection
525−i2 :: (Num e, CountableDimensions n m, FromLists e m n, FromLists e n n) => Matrix e n (Either m n)
540+i2 :: (Num e, CountableDims n m, FL m n, FL n n) => Matrix e n (Either m n)
526i2 = tr p2
541i2 = tr p2
528-- Dimensions
543-- Dimensions
530-- | Obtain the number of rows.
545-- | Obtain the number of rows.
532−-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
547+-- NOTE: The 'KnownNat' constraint is needed in order to obtain the
533−-- dimensions in constant time.
548+-- dimensions in constant time. For a version that doesn't require the
534−--
549+-- constraint see 'rows''.
535−-- TODO: A 'rows' function that does not need the 'KnownNat' constraint in
536−-- exchange for performance.
537rows :: forall e cols rows. (Countable rows) => Matrix e cols rows -> Int
550rows :: forall e cols rows. (Countable rows) => Matrix e cols rows -> Int
538rows _ = fromInteger $ natVal (Proxy :: Proxy (Count rows))
551rows _ = fromInteger $ natVal (Proxy :: Proxy (Count rows))
553+-- | Obtain the number of rows in an inefficient manner, but without any
556+-- For a more efficient version see 'rows'.
557+rows' :: Matrix e cols rows -> Int
559+rows' (Join lhs _) = rows' lhs
560+rows' (Fork top bottom) = rows' top + rows' bottom
540-- | Obtain the number of columns.
562-- | Obtain the number of columns.
542−-- NOTE: The 'KnownNat' constaint is needed in order to obtain the
543−-- dimensions in constant time.
545−-- TODO: A 'columns' function that does not need the 'KnownNat' constraint in
564+-- NOTE: The 'KnownNat' constraint is needed in order to obtain the
546−-- exchange for performance.
565+-- dimensions in constant time. For a version that doesn't require the
566+-- constraint see 'columns''.
547columns :: forall e cols rows. (Countable cols) => Matrix e cols rows -> Int
567columns :: forall e cols rows. (Countable cols) => Matrix e cols rows -> Int
548columns _ = fromInteger $ natVal (Proxy :: Proxy (Count cols))
568columns _ = fromInteger $ natVal (Proxy :: Proxy (Count cols))
570+-- | Obtain the number of columns in an inefficient manner, but without any
573+-- For a more efficient version see 'columns'.
574+columns' :: Matrix e cols rows -> Int
576+columns' (Join lhs rhs) = columns' lhs + columns' rhs
577+columns' (Fork top _) = columns' top
550-- Coproduct Bifunctor
579-- Coproduct Bifunctor
552infixl 5 -|-
581infixl 5 -|-
@@ -555,164 +584,161 @@ infixl 5 -|-
556 forall e n k m j.
585 forall e n k m j.
558− CountableDimensions j k,
587+ CountableDims j k,
559− FromLists e k k,
588+ FL k k,
560− FromLists e j k,
589+ FL j k,
561− FromLists e k j,
590+ FL k j,
562− FromLists e j j
591+ FL j j
564 Matrix e n k ->
593 Matrix e n k ->
565 Matrix e m j ->
594 Matrix e m j ->
566 Matrix e (Either n m) (Either k j)
595 Matrix e (Either n m) (Either k j)
567−(-|-) a b = Junc (i1 . a) (i2 . b)
596+(-|-) a b = Join (i1 . a) (i2 . b)
569-- Khatri Rao Product and projections
598-- Khatri Rao Product and projections
571-- | Khatri Rao product first component projection matrix.
600-- | Khatri Rao product first component projection matrix.
573 forall e m k .
602 forall e m k .
575− CountableDimensions k m,
604+ CountableDims k m,
576− FromLists e (Normalize (m, k)) m,
605+ FL (Normalize (m, k)) m,
577 CountableN (m, k)
606 CountableN (m, k)
578 ) => Matrix e (Normalize (m, k)) m
607 ) => Matrix e (Normalize (m, k)) m
579−kp1 = matrixBuilder f
608+fstM = matrixBuilder' f
581 offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
610 offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
583 | y >= (x * offset) && y <= (x * offset + offset - 1) = 1
612 | y >= (x * offset) && y <= (x * offset + offset - 1) = 1
584− | otherwise = 0
613+ | otherwise = 0
586-- | Khatri Rao product second component projection matrix.
615-- | Khatri Rao product second component projection matrix.
588 forall e m k .
617 forall e m k .
590− CountableDimensions k m,
619+ CountableDims k m,
591− FromLists e (Normalize (m, k)) k,
620+ FL (Normalize (m, k)) k,
592 CountableN (m, k)
621 CountableN (m, k)
593 ) => Matrix e (Normalize (m, k)) k
622 ) => Matrix e (Normalize (m, k)) k
594−kp2 = matrixBuilder f
623+sndM = matrixBuilder' f
596 offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
625 offset = fromInteger (natVal (Proxy :: Proxy (Count k)))
598 | x == y || mod (y - x) offset == 0 = 1
627 | x == y || mod (y - x) offset == 0 = 1
599− | otherwise = 0
628+ | otherwise = 0
601-- | Khatri Rao Matrix product also known as matrix pairing.
630-- | Khatri Rao Matrix product also known as matrix pairing.
603-- NOTE: That this is not a true categorical product, see for instance:
632-- NOTE: That this is not a true categorical product, see for instance:
606−-- | kp1 . khatri a b == a
635+-- | fstM . kr a b == a
607−-- khatri a b ==> |
636+-- kr a b ==> |
608−-- | kp2 . khatri a b == b
637+-- | sndM . kr a b == b
611-- __Emphasis__ on the implication symbol.
640-- __Emphasis__ on the implication symbol.
613− forall e cols a b.
642+ forall e cols a b.
615− CountableDimensions a b,
644+ CountableDims a b,
616 CountableN (a, b),
645 CountableN (a, b),
617− FromLists e (Normalize (a, b)) a,
646+ FL (Normalize (a, b)) a,
618− FromLists e (Normalize (a, b)) b
647+ FL (Normalize (a, b)) b
619 ) => Matrix e cols a -> Matrix e cols b -> Matrix e cols (Normalize (a, b))
648 ) => Matrix e cols a -> Matrix e cols b -> Matrix e cols (Normalize (a, b))
620−khatri a b =
649+kr a b =
621− let kp1' = kp1 @e @a @b
650+ let fstM' = fstM @e @a @b
622− kp2' = kp2 @e @a @b
651+ sndM' = sndM @e @a @b
623− in (tr kp1') . a * (tr kp2') . b
652+ in (tr fstM' . a) * (tr sndM' . b)
625-- Product Bifunctor (Kronecker)
654-- Product Bifunctor (Kronecker)
627infixl 4 ><
656infixl 4 ><
629-- | Matrix product functor also known as kronecker product
658-- | Matrix product functor also known as kronecker product
631− forall e m p n q.
660+ forall e m p n q.
633− CountableDimensions m n,
662+ CountableDims m n,
634− CountableDimensions p q,
663+ CountableDims p q,
635− CountableDimensionsN (m, n) (p, q),
664+ CountableDimsN (m, n) (p, q),
636− FromLists e (Normalize (m, n)) m,
665+ FL (Normalize (m, n)) m,
637− FromLists e (Normalize (m, n)) n,
666+ FL (Normalize (m, n)) n,
638− FromLists e (Normalize (p, q)) p,
667+ FL (Normalize (p, q)) p,
639− FromLists e (Normalize (p, q)) q
668+ FL (Normalize (p, q)) q
641 => Matrix e m p -> Matrix e n q -> Matrix e (Normalize (m, n)) (Normalize (p, q))
670 => Matrix e m p -> Matrix e n q -> Matrix e (Normalize (m, n)) (Normalize (p, q))
642(><) a b =
671(><) a b =
643− let kp1' = kp1 @e @m @n
672+ let fstM' = fstM @e @m @n
644− kp2' = kp2 @e @m @n
673+ sndM' = sndM @e @m @n
645− in khatri (a . kp1') (b . kp2')
674+ in kr (a . fstM') (b . sndM')
647−-- Matrix abide Junc Split
676+-- Matrix abide Join Fork
649−-- | Matrix "abiding" followin the 'Junc'-'Split' abide law.
678+-- | Matrix "abiding" following the 'Join'-'Fork' exchange law.
654−-- 'Junc' ('Split' a c) ('Split' b d) == 'Split' ('Junc' a b) ('Junc' c d)
683+-- 'Join' ('Fork' a c) ('Fork' b d) == 'Fork' ('Join' a b) ('Join' c d)
656−abideJS :: Matrix e cols rows -> Matrix e cols rows
685+abideJF :: Matrix e cols rows -> Matrix e cols rows
657−abideJS (Junc (Split a c) (Split b d)) = Split (Junc (abideJS a) (abideJS b)) (Junc (abideJS c) (abideJS d)) -- Junc-Split abide law
686+abideJF (Join (Fork a c) (Fork b d)) = Fork (Join (abideJF a) (abideJF b)) (Join (abideJF c) (abideJF d)) -- Join-Fork abide law
658−abideJS Empty = Empty
659−abideJS (One e) = One e
687+abideJF (One e) = One e
660−abideJS (Junc a b) = Junc (abideJS a) (abideJS b)
688+abideJF (Join a b) = Join (abideJF a) (abideJF b)
661−abideJS (Split a b) = Split (abideJS a) (abideJS b)
689+abideJF (Fork a b) = Fork (abideJF a) (abideJF b)
663−-- Matrix abide Split Junc
691+-- Matrix abide Fork Join
665−-- | Matrix "abiding" followin the 'Split'-'Junc' abide law.
693+-- | Matrix "abiding" followin the 'Fork'-'Join' abide law.
668−-- 'Split' ('Junc' a b) ('Junc' c d) == 'Junc' ('Split' a c) ('Split' b d)
696+-- 'Fork' ('Join' a b) ('Join' c d) == 'Join' ('Fork' a c) ('Fork' b d)
670−abideSJ :: Matrix e cols rows -> Matrix e cols rows
698+abideFJ :: Matrix e cols rows -> Matrix e cols rows
671−abideSJ (Split (Junc a b) (Junc c d)) = Junc (Split (abideSJ a) (abideSJ c)) (Split (abideSJ b) (abideSJ d)) -- Split-Junc abide law
699+abideFJ (Fork (Join a b) (Join c d)) = Join (Fork (abideFJ a) (abideFJ c)) (Fork (abideFJ b) (abideFJ d)) -- Fork-Join abide law
672−abideSJ Empty = Empty
673−abideSJ (One e) = One e
700+abideFJ (One e) = One e
674−abideSJ (Junc a b) = Junc (abideSJ a) (abideSJ b)
701+abideFJ (Join a b) = Join (abideFJ a) (abideFJ b)
675−abideSJ (Split a b) = Split (abideSJ a) (abideSJ b)
702+abideFJ (Fork a b) = Fork (abideFJ a) (abideFJ b)
677-- Matrix transposition
704-- Matrix transposition
679-- | Matrix transposition.
706-- | Matrix transposition.
680tr :: Matrix e cols rows -> Matrix e rows cols
707tr :: Matrix e cols rows -> Matrix e rows cols
682−tr (One e) = One e
708+tr (One e) = One e
683−tr (Junc a b) = Split (tr a) (tr b)
709+tr (Join a b) = Fork (tr a) (tr b)
684−tr (Split a b) = Junc (tr a) (tr b)
710+tr (Fork a b) = Join (tr a) (tr b)
686-- Selective 'select' operator
712-- Selective 'select' operator
688-- | Selective functors 'select' operator equivalent inspired by the
714-- | Selective functors 'select' operator equivalent inspired by the
689-- ArrowMonad solution presented in the paper.
715-- ArrowMonad solution presented in the paper.
690−select :: (Num e, FromLists e b b, Countable b) => Matrix e cols (Either a b) -> Matrix e a b -> Matrix e cols b
716+select :: (Num e, FL b b, Countable b) => Matrix e cols (Either a b) -> Matrix e a b -> Matrix e cols b
691−select (Split a b) y = y . a + b -- Divide-and-conquer law
717+select (Fork a b) y = y . a + b -- Divide-and-conquer law
692−select (Junc (Split a c) (Split b d)) y = junc (y . a + c) (y . b + d) -- Pattern matching + DnC law
718+select (Join (Fork a c) (Fork b d)) y = join (y . a + c) (y . b + d) -- Pattern matching + DnC law
693−select m y = junc y identity . m
719+select m y = join y id . m
697− CountableDimensions a b,
723+ CountableDims a b,
698− CountableDimensions c (Either b c),
724+ CountableDims c (Either b c),
699− FromLists e c b,
725+ FL c b,
700− FromLists e a b,
726+ FL a b,
701− FromLists e a a,
727+ FL a a,
702− FromLists e b b,
728+ FL b b,
703− FromLists e c c,
729+ FL c c,
704− FromLists e b a,
730+ FL b a,
705− FromLists e b c,
731+ FL b c,
706− FromLists e (Either b c) b,
732+ FL (Either b c) b,
707− FromLists e (Either b c) c
733+ FL (Either b c) c
709 => Matrix e cols (Either a b) -> Matrix e a c -> Matrix e b c -> Matrix e cols c
735 => Matrix e cols (Either a b) -> Matrix e a c -> Matrix e b c -> Matrix e cols c
710branch x l r = f x `select` g l `select` r
736branch x l r = f x `select` g l `select` r
712− f :: (Num e, Countable a, CountableDimensions b c, FromLists e a b, FromLists e c b, FromLists e b b, FromLists e b a, FromLists e a a)
738+ f :: (Num e, Countable a, CountableDims b c, FL a b, FL c b, FL b b, FL b a, FL a a)
713 => Matrix e cols (Either a b) -> Matrix e cols (Either a (Either b c))
739 => Matrix e cols (Either a b) -> Matrix e cols (Either a (Either b c))
714− f m = split (tr i1) (i1 . tr i2) . m
740+ f m = fork (tr i1) (i1 . tr i2) . m
715− g :: (Num e, CountableDimensions b c, FromLists e b c, FromLists e c c) => Matrix e a c -> Matrix e a (Either b c)
741+ g :: (Num e, CountableDims b c, FL b c, FL c c) => Matrix e a c -> Matrix e a (Either b c)
716 g m = i2 . m
742 g m = i2 . m
718-- McCarthy's Conditional
744-- McCarthy's Conditional
@@ -721,9 +747,9 @@ branch x l r = f x `select` g l `select` r
722 ( Trivial cols,
748 ( Trivial cols,
723 Countable cols,
749 Countable cols,
724− FromLists e () cols,
750+ FL () cols,
725− FromLists e cols (),
751+ FL cols (),
726− FromLists e cols cols,
752+ FL cols cols,
727 Bounded a,
753 Bounded a,
@@ -731,14 +757,14 @@ cond ::
733 (a -> Bool) -> Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
759 (a -> Bool) -> Matrix e cols rows -> Matrix e cols rows -> Matrix e cols rows
734−cond p f g = junc f g . grd p
760+cond p f g = join f g . grd p
737 ( Trivial q,
763 ( Trivial q,
738 Countable q,
764 Countable q,
739− FromLists e () q,
765+ FL () q,
740− FromLists e q (),
766+ FL q (),
741− FromLists e q q,
767+ FL q q,
742 Bounded a,
768 Bounded a,
@@ -746,44 +772,44 @@ grd ::
748 (a -> Bool) -> Matrix e q (Either q q)
774 (a -> Bool) -> Matrix e q (Either q q)
749−grd f = split (corr f) (corr (not . f))
775+grd f = fork (corr f) (corr (not . f))
752− forall e a q .
778+ forall e a q .
753 ( Trivial q,
779 ( Trivial q,
754 Countable q,
780 Countable q,
755− FromLists e () q,
781+ FL () q,
756− FromLists e q (),
782+ FL q (),
757− FromLists e q q,
783+ FL q q,
758 Liftable e a Bool
784 Liftable e a Bool
760 => (a -> Bool) -> Matrix e q q
786 => (a -> Bool) -> Matrix e q q
761−corr p = let f = fromF p :: Matrix e q ()
787+corr p = let f = fromF' p :: Matrix e q ()
762− in khatri f (identity :: Matrix e q q)
788+ in kr f (id :: Matrix e q q)
764-- Pretty print
790-- Pretty print
766prettyAux :: Show e => [[e]] -> [[e]] -> String
792prettyAux :: Show e => [[e]] -> [[e]] -> String
767prettyAux [] _ = ""
793prettyAux [] _ = ""
768−prettyAux [[e]] m = "│ " ++ fill (show e) ++ " │\n"
794+prettyAux [[e]] m = "│ " ++ fill (show e) ++ " │\n"
770 v = fmap show m
796 v = fmap show m
771 widest = maximum $ fmap length v
797 widest = maximum $ fmap length v
772 fill str = replicate (widest - length str - 2) ' ' ++ str
798 fill str = replicate (widest - length str - 2) ' ' ++ str
773−prettyAux [h] m = "│ " ++ fill (unwords $ map show h) ++ " │\n"
799+prettyAux [h] m = "│ " ++ fill (unwords $ map show h) ++ " │\n"
775− v = fmap show m
801+ v = fmap show m
776− widest = maximum $ fmap length v
802+ widest = maximum $ fmap length v
777 fill str = replicate (widest - length str - 2) ' ' ++ str
803 fill str = replicate (widest - length str - 2) ' ' ++ str
778−prettyAux (h : t) l = "│ " ++ fill (unwords $ map show h) ++ " │\n" ++
804+prettyAux (h : t) l = "│ " ++ fill (unwords $ map show h) ++ " │\n" ++
779 prettyAux t l
805 prettyAux t l
781− v = fmap show l
807+ v = fmap show l
782− widest = maximum $ fmap length v
808+ widest = maximum $ fmap length v
783 fill str = replicate (widest - length str - 2) ' ' ++ str
809 fill str = replicate (widest - length str - 2) ' ' ++ str
785-- | Matrix pretty printer
811-- | Matrix pretty printer
786−pretty :: (CountableDimensions cols rows, Show e) => Matrix e cols rows -> String
812+pretty :: (CountableDims cols rows, Show e) => Matrix e cols rows -> String
787pretty m = concat
813pretty m = concat
788 [ "┌ ", unwords (replicate (columns m) blank), " ┐\n"
814 [ "┌ ", unwords (replicate (columns m) blank), " ┐\n"
789 , unlines
815 , unlines
@@ -791,16 +817,16 @@ pretty m = concat
791 , "└ ", unwords (replicate (columns m) blank), " ┘"
817 , "└ ", unwords (replicate (columns m) blank), " ┘"
794− strings = map show (toList m)
820+ strings = map show (toList m)
795− widest = maximum $ map length strings
821+ widest = maximum $ map length strings
796 fill str = replicate (widest - length str) ' ' ++ str
822 fill str = replicate (widest - length str) ' ' ++ str
797− blank = fill ""
823+ blank = fill ""
798 safeGet i j m
824 safeGet i j m
799 | i > rows m || j > columns m || i < 1 || j < 1 = Nothing
825 | i > rows m || j > columns m || i < 1 || j < 1 = Nothing
800 | otherwise = Just $ unsafeGet i j m (toList m)
826 | otherwise = Just $ unsafeGet i j m (toList m)
801 unsafeGet i j m l = l !! encode (columns m) (i,j)
827 unsafeGet i j m l = l !! encode (columns m) (i,j)
802− encode m (i,j) = (i-1)*m + j - 1
828+ encode m (i,j) = (i-1)*m + j - 1
803− getElem i j m =
829+ getElem i j m =
804 fromMaybe
830 fromMaybe
806 "getElem: Trying to get the "
832 "getElem: Trying to get the "
@@ -812,21 +838,20 @@ pretty m = concat
812 (safeGet i j m)
838 (safeGet i j m)
814-- | Matrix pretty printer
840-- | Matrix pretty printer
815−prettyPrint :: (CountableDimensions cols rows, Show e) => Matrix e cols rows -> IO ()
841+prettyPrint :: (CountableDims cols rows, Show e) => Matrix e cols rows -> IO ()
816prettyPrint = putStrLn . pretty
842prettyPrint = putStrLn . pretty
818-- | Zip two matrices with a given binary function
844-- | Zip two matrices with a given binary function
819zipWithM :: (e -> f -> g) -> Matrix e cols rows -> Matrix f cols rows -> Matrix g cols rows
845zipWithM :: (e -> f -> g) -> Matrix e cols rows -> Matrix f cols rows -> Matrix g cols rows
820−zipWithM f Empty Empty = Empty
821−zipWithM f (One a) (One b) = One (f a b)
846+zipWithM f (One a) (One b) = One (f a b)
822−zipWithM f (Junc a b) (Junc c d) = Junc (zipWithM f a c) (zipWithM f b d)
847+zipWithM f (Join a b) (Join c d) = Join (zipWithM f a c) (zipWithM f b d)
823−zipWithM f (Split a b) (Split c d) = Split (zipWithM f a c) (zipWithM f b d)
848+zipWithM f (Fork a b) (Fork c d) = Fork (zipWithM f a c) (zipWithM f b d)
824−zipWithM f x@(Split _ _) y@(Junc _ _) = zipWithM f x (abideJS y)
849+zipWithM f x@(Fork _ _) y@(Join _ _) = zipWithM f x (abideJF y)
825−zipWithM f x@(Junc _ _) y@(Split _ _) = zipWithM f (abideJS x) y
850+zipWithM f x@(Join _ _) y@(Fork _ _) = zipWithM f (abideJF x) y
827-- Relational operators functions
852-- Relational operators functions
829−type Boolean = Natural 0 1
854+type Boolean = Natural 0 1
830type Relation a b = Matrix Boolean a b
855type Relation a b = Matrix Boolean a b
832-- | Helper conversion function
857-- | Helper conversion function
@@ -842,54 +867,47 @@ fromBool False = nat 0
843-- | Relational negation
868-- | Relational negation
844negateM :: Relation cols rows -> Relation cols rows
869negateM :: Relation cols rows -> Relation cols rows
845−negateM Empty = Empty
846−negateM (One (Nat 0)) = One (Nat 1)
870+negateM (One (Nat p)) = One (Nat (negate p))
847−negateM (One (Nat 1)) = One (Nat 0)
848−negateM (Junc a b) = Junc (negateM a) (negateM b)
871+negateM (Join a b) = Join (negateM a) (negateM b)
849−negateM (Split a b) = Split (negateM a) (negateM b)
872+negateM (Fork a b) = Fork (negateM a) (negateM b)
851-- | Relational addition
874-- | Relational addition
852orM :: Relation cols rows -> Relation cols rows -> Relation cols rows
875orM :: Relation cols rows -> Relation cols rows -> Relation cols rows
853−orM Empty Empty = Empty
854−orM (One a) (One b) = One (fromBool (toBool a || toBool b))
876+orM (One a) (One b) = One (fromBool (toBool a || toBool b))
855−orM (Junc a b) (Junc c d) = Junc (orM a c) (orM b d)
877+orM (Join a b) (Join c d) = Join (orM a c) (orM b d)
856−orM (Split a b) (Split c d) = Split (orM a c) (orM b d)
878+orM (Fork a b) (Fork c d) = Fork (orM a c) (orM b d)
857−orM x@(Split _ _) y@(Junc _ _) = orM x (abideJS y)
879+orM x@(Fork _ _) y@(Join _ _) = orM x (abideJF y)
858−orM x@(Junc _ _) y@(Split _ _) = orM (abideJS x) y
880+orM x@(Join _ _) y@(Fork _ _) = orM (abideJF x) y
860-- | Relational multiplication
882-- | Relational multiplication
861andM :: Relation cols rows -> Relation cols rows -> Relation cols rows
883andM :: Relation cols rows -> Relation cols rows -> Relation cols rows
862−andM Empty Empty = Empty
863−andM (One a) (One b) = One (fromBool (toBool a && toBool b))
884+andM (One a) (One b) = One (fromBool (toBool a && toBool b))
864−andM (Junc a b) (Junc c d) = Junc (andM a c) (andM b d)
885+andM (Join a b) (Join c d) = Join (andM a c) (andM b d)
865−andM (Split a b) (Split c d) = Split (andM a c) (andM b d)
886+andM (Fork a b) (Fork c d) = Fork (andM a c) (andM b d)
866−andM x@(Split _ _) y@(Junc _ _) = andM x (abideJS y)
887+andM x@(Fork _ _) y@(Join _ _) = andM x (abideJF y)
867−andM x@(Junc _ _) y@(Split _ _) = andM (abideJS x) y
888+andM x@(Join _ _) y@(Fork _ _) = andM (abideJF x) y
869-- | Relational subtraction
890-- | Relational subtraction
870subM :: Relation cols rows -> Relation cols rows -> Relation cols rows
891subM :: Relation cols rows -> Relation cols rows -> Relation cols rows
871−subM Empty Empty = Empty
872−subM (One a) (One b) = if a - b < nat 0 then One (nat 0) else One (a - b)
892+subM (One a) (One b) = if a - b < nat 0 then One (nat 0) else One (a - b)
873−subM (Junc a b) (Junc c d) = Junc (subM a c) (subM b d)
893+subM (Join a b) (Join c d) = Join (subM a c) (subM b d)
874−subM (Split a b) (Split c d) = Split (subM a c) (subM b d)
894+subM (Fork a b) (Fork c d) = Fork (subM a c) (subM b d)
875−subM x@(Split _ _) y@(Junc _ _) = subM x (abideJS y)
895+subM x@(Fork _ _) y@(Join _ _) = subM x (abideJF y)
876−subM x@(Junc _ _) y@(Split _ _) = subM (abideJS x) y
896+subM x@(Join _ _) y@(Fork _ _) = subM (abideJF x) y
878-- | Matrix relational composition.
898-- | Matrix relational composition.
879compRel :: Relation cr rows -> Relation cols cr -> Relation cols rows
899compRel :: Relation cr rows -> Relation cols cr -> Relation cols rows
880−compRel Empty Empty = Empty
881−compRel (One a) (One b) = One (fromBool (toBool a && toBool b))
900+compRel (One a) (One b) = One (fromBool (toBool a && toBool b))
882−compRel (Junc a b) (Split c d) = orM (compRel a c) (compRel b d) -- Divide-and-conquer law
901+compRel (Join a b) (Fork c d) = orM (compRel a c) (compRel b d) -- Divide-and-conquer law
883−compRel (Split a b) c = Split (compRel a c) (compRel b c) -- Split fusion law
902+compRel (Fork a b) c = Fork (compRel a c) (compRel b c) -- Fork fusion law
884−compRel c (Junc a b) = Junc (compRel c a) (compRel c b) -- Junc fusion law
903+compRel c (Join a b) = Join (compRel c a) (compRel c b) -- Join fusion law
886-- | Matrix relational right division
905-- | Matrix relational right division
887divR :: Relation b c -> Relation b a -> Relation a c
906divR :: Relation b c -> Relation b a -> Relation a c
888−divR Empty Empty = Empty
889divR (One a) (One b) = One (fromBool (not (toBool b) || toBool a)) -- b implies a
907divR (One a) (One b) = One (fromBool (not (toBool b) || toBool a)) -- b implies a
890−divR (Junc a b) (Junc c d) = andM (divR a c) (divR b d)
908+divR (Join a b) (Join c d) = andM (divR a c) (divR b d)
891−divR (Split a b) c = Split (divR a c) (divR b c)
909+divR (Fork a b) c = Fork (divR a c) (divR b c)
892−divR c (Split a b) = Junc (divR c a) (divR c b)
910+divR c (Fork a b) = Join (divR c a) (divR c b)
894-- | Matrix relational left division
912-- | Matrix relational left division
895divL :: Relation c b -> Relation a b -> Relation a c
913divL :: Relation c b -> Relation a b -> Relation a c
@@ -905,86 +923,52 @@ divS s r = divL r s `intersection` divR (tr r) (tr s)
906-- NOTE: Be careful to not ask for a relation bigger than the cardinality of
924-- NOTE: Be careful to not ask for a relation bigger than the cardinality of
907-- types @a@ or @b@ allows.
925-- types @a@ or @b@ allows.
908−fromFRel ::
926+fromFRel' ::
909 forall a b cols rows.
927 forall a b cols rows.
910 ( Liftable Boolean a b,
928 ( Liftable Boolean a b,
911− CountableDimensions cols rows,
929+ CountableDims cols rows,
912− FromLists Boolean rows cols
930+ FL rows cols
914 (a -> b) ->
932 (a -> b) ->
915 Relation cols rows
933 Relation cols rows
916−fromFRel f =
934+fromFRel' = fromF'
917− let minA = minBound @a
921− ccols = fromInteger $ natVal (Proxy :: Proxy (Count cols))
922− rrows = fromInteger $ natVal (Proxy :: Proxy (Count rows))
923− elementsA = take ccols [minA .. maxA]
924− elementsB = take rrows [minB .. maxB]
925− combinations = (,) <$> elementsA <*> elementsB
926− combAp = map snd . sort . map (\(a, b) -> if f a == b
927− then ((fromEnum a, fromEnum b), nat 1)
928− else ((fromEnum a, fromEnum b), nat 0)) $ combinations
929− mList = buildList combAp rrows
930− in tr $ fromLists mList
933− buildList l r = take r l : buildList (drop r l) r
935-- | Lifts functions to relations with dimensions matching @a@ and @b@
936-- | Lifts functions to relations with dimensions matching @a@ and @b@
936-- cardinality's.
937-- cardinality's.
937−fromFRel' ::
938+fromFRel ::
938 forall a b.
939 forall a b.
939 ( Liftable Boolean a b,
940 ( Liftable Boolean a b,
940− CountableDimensionsN a b,
941+ CountableDimsN a b,
941− FromLists Boolean (Normalize b) (Normalize a)
942+ FLN b a
943 (a -> b) ->
944 (a -> b) ->
944 Relation (Normalize a) (Normalize b)
945 Relation (Normalize a) (Normalize b)
945−fromFRel' f =
946+fromFRel = fromFRel'
946− let minA = minBound @a
950− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
951− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
952− elementsA = take ccols [minA .. maxA]
953− elementsB = take rrows [minB .. maxB]
954− combinations = (,) <$> elementsA <*> elementsB
955− combAp = map snd . sort . map (\(a, b) -> if f a == b
956− then ((fromEnum a, fromEnum b), nat 1)
957− else ((fromEnum a, fromEnum b), nat 0)) $ combinations
958− mList = buildList combAp rrows
959− in tr $ fromLists mList
962− buildList l r = take r l : buildList (drop r l) r
964-- | Lifts a relation function to a Boolean Matrix
948-- | Lifts a relation function to a Boolean Matrix
965−toRel ::
949+toRel ::
966 forall a b.
950 forall a b.
967 ( Bounded a,
951 ( Bounded a,
968 Bounded b,
952 Bounded b,
972− CountableDimensionsN a b,
956+ CountableDims a b,
973− FromListsN Boolean b a
957+ FLN b a
975 => (a -> b -> Bool) -> Relation (Normalize a) (Normalize b)
959 => (a -> b -> Bool) -> Relation (Normalize a) (Normalize b)
977 let minA = minBound @a
961 let minA = minBound @a
978 maxA = maxBound @a
962 maxA = maxBound @a
979 minB = minBound @b
963 minB = minBound @b
980 maxB = maxBound @b
964 maxB = maxBound @b
981− ccols = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize a)))
965+ ccols = fromInteger $ natVal (Proxy :: Proxy (Count a))
982− rrows = fromInteger $ natVal (Proxy :: Proxy (Count (Normalize b)))
966+ rrows = fromInteger $ natVal (Proxy :: Proxy (Count b))
983 elementsA = take ccols [minA .. maxA]
967 elementsA = take ccols [minA .. maxA]
984 elementsB = take rrows [minB .. maxB]
968 elementsB = take rrows [minB .. maxB]
985 combinations = (,) <$> elementsA <*> elementsB
969 combinations = (,) <$> elementsA <*> elementsB
986− combAp = map snd . sort . map (\(a, b) -> if uncurry f (a, b)
970+ combAp = map snd . sort . map (\(a, b) -> if uncurry f (a, b)
987− then ((fromEnum a, fromEnum b), nat 1)
971+ then ((fromEnum a, fromEnum b), nat 1)
988 else ((fromEnum a, fromEnum b), nat 0)) $ combinations
972 else ((fromEnum a, fromEnum b), nat 0)) $ combinations
989 mList = buildList combAp rrows
973 mList = buildList combAp rrows
990 in tr $ fromLists mList
974 in tr $ fromLists mList