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