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