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